Skip to content

Commit 72d79d1

Browse files
committed
Add more flexible registration of DefaultMethodEndpointAdapter
This commit updates WsConfigurer to get a callback with the list of default method argument resolvers and return value handlers. Previously, the callback only allowed to add custom instances and these were added after the defaults. Closes gh-1080
1 parent ef00c3e commit 72d79d1

File tree

5 files changed

+135
-60
lines changed

5 files changed

+135
-60
lines changed

spring-ws-core/src/main/java/org/springframework/ws/config/annotation/WsConfigurationSupport.java

+15-13
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
package org.springframework.ws.config.annotation;
1818

1919
import java.util.ArrayList;
20+
import java.util.LinkedList;
2021
import java.util.List;
2122

2223
import org.springframework.context.annotation.Bean;
@@ -141,37 +142,38 @@ protected void addInterceptors(List<EndpointInterceptor> interceptors) {
141142
* annotated endpoint methods. Consider overriding one of these other more
142143
* fine-grained methods:
143144
* <ul>
144-
* <li>{@link #addArgumentResolvers(List)} for adding custom argument resolvers.
145-
* <li>{@link #addReturnValueHandlers(List)} for adding custom return value handlers.
145+
* <li>{@link #addArgumentResolvers(List)} for configuring the argument resolvers.
146+
* <li>{@link #addReturnValueHandlers(List)} for configuring the return value
147+
* handlers.
146148
* </ul>
147149
*/
148150
@Bean
149151
public DefaultMethodEndpointAdapter defaultMethodEndpointAdapter() {
150-
List<MethodArgumentResolver> argumentResolvers = new ArrayList<>();
152+
DefaultMethodEndpointAdapter adapter = DefaultMethodEndpointAdapter.withDefaults();
153+
LinkedList<MethodArgumentResolver> argumentResolvers = new LinkedList<>(adapter.getMethodArgumentResolvers());
151154
addArgumentResolvers(argumentResolvers);
155+
adapter.setMethodArgumentResolvers(argumentResolvers);
152156

153-
List<MethodReturnValueHandler> returnValueHandlers = new ArrayList<>();
157+
LinkedList<MethodReturnValueHandler> returnValueHandlers = new LinkedList<>(
158+
adapter.getMethodReturnValueHandlers());
154159
addReturnValueHandlers(returnValueHandlers);
155-
156-
DefaultMethodEndpointAdapter adapter = new DefaultMethodEndpointAdapter();
157-
adapter.setCustomMethodArgumentResolvers(argumentResolvers);
158-
adapter.setCustomMethodReturnValueHandlers(returnValueHandlers);
160+
adapter.setMethodReturnValueHandlers(returnValueHandlers);
159161

160162
return adapter;
161163
}
162164

163165
/**
164-
* Add custom {@link MethodArgumentResolver}s to use in addition to the ones
166+
* Configure the {@link MethodArgumentResolver}s to use in addition to the ones
165167
* registered by default.
166-
* @param argumentResolvers the list of custom converters; initially an empty list.
168+
* @param argumentResolvers the list of resolvers; initially the default resolvers
167169
*/
168170
protected void addArgumentResolvers(List<MethodArgumentResolver> argumentResolvers) {
169171
}
170172

171173
/**
172-
* Add custom {@link MethodReturnValueHandler}s in addition to the ones registered by
173-
* default.
174-
* @param returnValueHandlers the list of custom handlers; initially an empty list.
174+
* Configure the {@link MethodReturnValueHandler}s to use in addition to the ones
175+
* registered by default.
176+
* @param returnValueHandlers the list of handlers; initially the default handlers
175177
*/
176178
protected void addReturnValueHandlers(List<MethodReturnValueHandler> returnValueHandlers) {
177179
}

spring-ws-core/src/main/java/org/springframework/ws/config/annotation/WsConfigurer.java

+6-8
Original file line numberDiff line numberDiff line change
@@ -43,20 +43,18 @@ default void addInterceptors(List<EndpointInterceptor> interceptors) {
4343
}
4444

4545
/**
46-
* Add resolvers to support custom endpoint method argument types.
47-
* @param argumentResolvers initially an empty list
46+
* Configure the {@link MethodArgumentResolver}s to use in addition to the ones
47+
* registered by default.
48+
* @param argumentResolvers the list of resolvers; initially the default resolvers
4849
*/
4950
default void addArgumentResolvers(List<MethodArgumentResolver> argumentResolvers) {
5051

5152
}
5253

5354
/**
54-
* Add handlers to support custom controller method return value types.
55-
* <p>
56-
* Using this option does not override the built-in support for handling return
57-
* values. To customize the built-in support for handling return values, configure
58-
* RequestMappingHandlerAdapter directly.
59-
* @param returnValueHandlers initially an empty list
55+
* Configure the {@link MethodReturnValueHandler}s to use in addition to the ones
56+
* registered by default.
57+
* @param returnValueHandlers the list of handlers; initially the default handlers
6058
*/
6159
default void addReturnValueHandlers(List<MethodReturnValueHandler> returnValueHandlers) {
6260

spring-ws-core/src/main/java/org/springframework/ws/server/endpoint/adapter/DefaultMethodEndpointAdapter.java

+20
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,16 @@ public class DefaultMethodEndpointAdapter extends AbstractMethodEndpointAdapter
7676

7777
private ClassLoader classLoader;
7878

79+
/**
80+
* Create a new instance with default method argument and return value resolvers.
81+
* @return a new instance with defaults configured
82+
*/
83+
public static DefaultMethodEndpointAdapter withDefaults() {
84+
DefaultMethodEndpointAdapter adapter = new DefaultMethodEndpointAdapter();
85+
adapter.initDefaultStrategies();
86+
return adapter;
87+
}
88+
7989
/**
8090
* Returns the list of {@code MethodArgumentResolver}s to use.
8191
*/
@@ -92,7 +102,9 @@ public void setMethodArgumentResolvers(List<MethodArgumentResolver> methodArgume
92102

93103
/**
94104
* Returns the custom argument resolvers.
105+
* @deprecated as of 4.1.0 with no replacement
95106
*/
107+
@Deprecated(since = "4.1.0", forRemoval = true)
96108
public List<MethodArgumentResolver> getCustomMethodArgumentResolvers() {
97109
return this.customMethodArgumentResolvers;
98110
}
@@ -101,7 +113,10 @@ public List<MethodArgumentResolver> getCustomMethodArgumentResolvers() {
101113
* Sets the custom handlers for method arguments. Custom handlers are ordered after
102114
* built-in ones. To override the built-in support for return value handling use
103115
* {@link #setMethodArgumentResolvers(List)}.
116+
* @deprecated as of 4.1.0 in favor of setting a single list
117+
* @see #withDefaults()
104118
*/
119+
@Deprecated(since = "4.1.0", forRemoval = true)
105120
public void setCustomMethodArgumentResolvers(List<MethodArgumentResolver> customMethodArgumentResolvers) {
106121
this.customMethodArgumentResolvers = customMethodArgumentResolvers;
107122
}
@@ -122,7 +137,9 @@ public void setMethodReturnValueHandlers(List<MethodReturnValueHandler> methodRe
122137

123138
/**
124139
* Returns the custom return value handlers.
140+
* @deprecated as of 4.1.0 with no replacement
125141
*/
142+
@Deprecated(since = "4.1.0", forRemoval = true)
126143
public List<MethodReturnValueHandler> getCustomMethodReturnValueHandlers() {
127144
return this.customMethodReturnValueHandlers;
128145
}
@@ -131,7 +148,10 @@ public List<MethodReturnValueHandler> getCustomMethodReturnValueHandlers() {
131148
* Sets the handlers for custom return value types. Custom handlers are ordered after
132149
* built-in ones. To override the built-in support for return value handling use
133150
* {@link #setMethodReturnValueHandlers(List)}.
151+
* @deprecated as of 4.1.0 in favor of setting a single list
152+
* @see #withDefaults()
134153
*/
154+
@Deprecated(since = "4.1.0", forRemoval = true)
135155
public void setCustomMethodReturnValueHandlers(List<MethodReturnValueHandler> customMethodReturnValueHandlers) {
136156
this.customMethodReturnValueHandlers = customMethodReturnValueHandlers;
137157
}

spring-ws-core/src/test/java/org/springframework/ws/config/annotation/WsConfigurationSupportTest.java

+87-33
Original file line numberDiff line numberDiff line change
@@ -18,82 +18,136 @@
1818

1919
import java.util.List;
2020

21-
import org.junit.jupiter.api.BeforeEach;
2221
import org.junit.jupiter.api.Test;
2322

24-
import org.springframework.context.ApplicationContext;
23+
import org.springframework.context.ConfigurableApplicationContext;
2524
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
2625
import org.springframework.context.annotation.Bean;
2726
import org.springframework.context.annotation.Configuration;
27+
import org.springframework.ws.config.annotation.WsConfigurationSupportTest.CustomArgumentResolverConfig.MyArgumentResolver;
28+
import org.springframework.ws.config.annotation.WsConfigurationSupportTest.CustomDefaultMethodEndpointAdapterConfig.MyDefaultMethodEndpointAdapter;
29+
import org.springframework.ws.config.annotation.WsConfigurationSupportTest.CustomInterceptorConfig.MyInterceptor;
30+
import org.springframework.ws.config.annotation.WsConfigurationSupportTest.CustomReturnValueHandlerConfig.MyReturnValueHandler;
2831
import org.springframework.ws.server.EndpointInterceptor;
2932
import org.springframework.ws.server.endpoint.adapter.DefaultMethodEndpointAdapter;
33+
import org.springframework.ws.server.endpoint.adapter.method.MethodArgumentResolver;
34+
import org.springframework.ws.server.endpoint.adapter.method.MethodReturnValueHandler;
35+
import org.springframework.ws.server.endpoint.adapter.method.SourcePayloadMethodProcessor;
3036
import org.springframework.ws.server.endpoint.interceptor.EndpointInterceptorAdapter;
3137
import org.springframework.ws.server.endpoint.mapping.PayloadRootAnnotationMethodEndpointMapping;
3238

3339
import static org.assertj.core.api.Assertions.assertThat;
3440

3541
/**
42+
* Tests for {@link WsConfigurationSupport}.
43+
*
3644
* @author Arjen Poutsma
45+
* @author Stephane Nicoll
3746
*/
38-
public class WsConfigurationSupportTest {
47+
class WsConfigurationSupportTest {
3948

40-
private ApplicationContext applicationContext;
49+
@Test
50+
void interceptors() {
51+
try (ConfigurableApplicationContext applicationContext = load(CustomInterceptorConfig.class)) {
52+
PayloadRootAnnotationMethodEndpointMapping endpointMapping = applicationContext
53+
.getBean(PayloadRootAnnotationMethodEndpointMapping.class);
54+
assertThat(endpointMapping.getOrder()).isEqualTo(0);
55+
EndpointInterceptor[] interceptors = endpointMapping.getInterceptors();
56+
assertThat(interceptors).singleElement().isInstanceOf(MyInterceptor.class);
57+
}
58+
}
4159

42-
@BeforeEach
43-
public void setUp() {
60+
@Test
61+
void argumentResolvers() {
62+
try (ConfigurableApplicationContext applicationContext = load(CustomArgumentResolverConfig.class)) {
63+
DefaultMethodEndpointAdapter bean = applicationContext.getBean(DefaultMethodEndpointAdapter.class);
64+
List<MethodArgumentResolver> methodArgumentResolvers = bean.getMethodArgumentResolvers();
65+
assertThat(methodArgumentResolvers).hasSizeGreaterThan(1).element(0).isInstanceOf(MyArgumentResolver.class);
66+
}
67+
}
68+
69+
@Test
70+
void returnValueHandlers() {
71+
try (ConfigurableApplicationContext applicationContext = load(CustomReturnValueHandlerConfig.class)) {
72+
DefaultMethodEndpointAdapter bean = applicationContext.getBean(DefaultMethodEndpointAdapter.class);
73+
List<MethodReturnValueHandler> methodReturnValueHandlers = bean.getMethodReturnValueHandlers();
74+
assertThat(methodReturnValueHandlers).hasSizeGreaterThan(1)
75+
.element(0)
76+
.isInstanceOf(MyReturnValueHandler.class);
77+
}
78+
}
4479

80+
@Test
81+
void defaultMethodEndpointAdapter() {
82+
try (ConfigurableApplicationContext applicationContext = load(CustomDefaultMethodEndpointAdapterConfig.class)) {
83+
assertThat(applicationContext.getBean(DefaultMethodEndpointAdapter.class))
84+
.isInstanceOf(MyDefaultMethodEndpointAdapter.class);
85+
}
86+
}
87+
88+
private ConfigurableApplicationContext load(Class<?>... componentClasses) {
4589
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
46-
applicationContext.register(TestConfig.class);
90+
applicationContext.register(componentClasses);
4791
applicationContext.refresh();
48-
49-
this.applicationContext = applicationContext;
92+
return applicationContext;
5093
}
5194

52-
@Test
53-
public void interceptors() {
95+
@Configuration(proxyBeanMethods = false)
96+
static class CustomInterceptorConfig extends WsConfigurationSupport {
5497

55-
PayloadRootAnnotationMethodEndpointMapping endpointMapping = this.applicationContext
56-
.getBean(PayloadRootAnnotationMethodEndpointMapping.class);
98+
@Override
99+
protected void addInterceptors(List<EndpointInterceptor> interceptors) {
100+
interceptors.add(new MyInterceptor());
101+
}
57102

58-
assertThat(endpointMapping.getOrder()).isEqualTo(0);
103+
static class MyInterceptor extends EndpointInterceptorAdapter {
59104

60-
EndpointInterceptor[] interceptors = endpointMapping.getInterceptors();
105+
}
61106

62-
assertThat(interceptors).hasSize(1);
63-
assertThat(interceptors[0]).isInstanceOf(MyInterceptor.class);
64107
}
65108

66-
@Test
67-
public void defaultMethodEndpointAdapter() {
109+
@Configuration(proxyBeanMethods = false)
110+
static class CustomArgumentResolverConfig extends WsConfigurationSupport {
111+
112+
@Override
113+
protected void addArgumentResolvers(List<MethodArgumentResolver> argumentResolvers) {
114+
assertThat(argumentResolvers).isNotEmpty();
115+
argumentResolvers.add(0, new MyArgumentResolver());
116+
}
68117

69-
DefaultMethodEndpointAdapter endpointAdapter = this.applicationContext
70-
.getBean(DefaultMethodEndpointAdapter.class);
118+
static class MyArgumentResolver extends SourcePayloadMethodProcessor {
119+
120+
}
71121

72-
assertThat(endpointAdapter).isNotNull();
73-
assertThat(endpointAdapter).isInstanceOf(MyDefaultMethodEndpointAdapter.class);
74122
}
75123

76-
@Configuration
77-
public static class TestConfig extends WsConfigurationSupport {
124+
@Configuration(proxyBeanMethods = false)
125+
static class CustomReturnValueHandlerConfig extends WsConfigurationSupport {
78126

79127
@Override
80-
protected void addInterceptors(List<EndpointInterceptor> interceptors) {
81-
interceptors.add(new MyInterceptor());
128+
protected void addReturnValueHandlers(List<MethodReturnValueHandler> returnValueHandlers) {
129+
assertThat(returnValueHandlers).isNotEmpty();
130+
returnValueHandlers.add(0, new MyReturnValueHandler());
131+
}
132+
133+
static class MyReturnValueHandler extends SourcePayloadMethodProcessor {
134+
82135
}
83136

137+
}
138+
139+
@Configuration(proxyBeanMethods = false)
140+
static class CustomDefaultMethodEndpointAdapterConfig extends WsConfigurationSupport {
141+
84142
@Bean
85143
@Override
86144
public DefaultMethodEndpointAdapter defaultMethodEndpointAdapter() {
87145
return new MyDefaultMethodEndpointAdapter();
88146
}
89147

90-
}
91-
92-
public static class MyInterceptor extends EndpointInterceptorAdapter {
148+
static class MyDefaultMethodEndpointAdapter extends DefaultMethodEndpointAdapter {
93149

94-
}
95-
96-
public static class MyDefaultMethodEndpointAdapter extends DefaultMethodEndpointAdapter {
150+
}
97151

98152
}
99153

spring-ws-core/src/test/java/org/springframework/ws/config/annotation/WsConfigurerAdapterTest.java

+7-6
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@
3838
/**
3939
* @author Arjen Poutsma
4040
*/
41+
@Deprecated
4142
public class WsConfigurerAdapterTest {
4243

4344
private ApplicationContext applicationContext;
@@ -72,9 +73,9 @@ public void argumentResolvers() {
7273
DefaultMethodEndpointAdapter endpointAdapter = this.applicationContext
7374
.getBean(DefaultMethodEndpointAdapter.class);
7475

75-
List<MethodArgumentResolver> argumentResolvers = endpointAdapter.getCustomMethodArgumentResolvers();
76+
List<MethodArgumentResolver> argumentResolvers = endpointAdapter.getMethodArgumentResolvers();
7677

77-
assertThat(argumentResolvers).hasSize(1);
78+
assertThat(argumentResolvers).hasSizeGreaterThan(1);
7879
assertThat(argumentResolvers.get(0)).isInstanceOf(MyMethodArgumentResolver.class);
7980

8081
argumentResolvers = endpointAdapter.getMethodArgumentResolvers();
@@ -88,9 +89,9 @@ public void returnValueHandlers() {
8889
DefaultMethodEndpointAdapter endpointAdapter = this.applicationContext
8990
.getBean(DefaultMethodEndpointAdapter.class);
9091

91-
List<MethodReturnValueHandler> returnValueHandlers = endpointAdapter.getCustomMethodReturnValueHandlers();
92+
List<MethodReturnValueHandler> returnValueHandlers = endpointAdapter.getMethodReturnValueHandlers();
9293

93-
assertThat(returnValueHandlers).hasSize(1);
94+
assertThat(returnValueHandlers).hasSizeGreaterThan(1);
9495
assertThat(returnValueHandlers.get(0)).isInstanceOf(MyReturnValueHandler.class);
9596

9697
returnValueHandlers = endpointAdapter.getMethodReturnValueHandlers();
@@ -109,12 +110,12 @@ public void addInterceptors(List<EndpointInterceptor> interceptors) {
109110

110111
@Override
111112
public void addArgumentResolvers(List<MethodArgumentResolver> argumentResolvers) {
112-
argumentResolvers.add(new MyMethodArgumentResolver());
113+
argumentResolvers.add(0, new MyMethodArgumentResolver());
113114
}
114115

115116
@Override
116117
public void addReturnValueHandlers(List<MethodReturnValueHandler> returnValueHandlers) {
117-
returnValueHandlers.add(new MyReturnValueHandler());
118+
returnValueHandlers.add(0, new MyReturnValueHandler());
118119
}
119120

120121
}

0 commit comments

Comments
 (0)