Skip to content

Commit 9f7159d

Browse files
committed
DATACMNS-987 Jackson converter gets only loaded iff jackson and jayway are present
Added a test for loading of QuerydslPredicateArgumentResolver, but it fails presumably because EnableSpringDataWebSupport is not in effect. Ignored that test for now, will fix it with DATACMNS-993. renamed SpringDataWebConfigurationUnitTests to SpringDataWebConfigurationIntegrationTests since it is actually an integration test.
1 parent 68308aa commit 9f7159d

File tree

3 files changed

+203
-104
lines changed

3 files changed

+203
-104
lines changed

src/main/java/org/springframework/data/web/config/SpringDataWebConfiguration.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2013-2016 the original author or authors.
2+
* Copyright 2013-2017 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -118,7 +118,8 @@ public void addArgumentResolvers(List<HandlerMethodArgumentResolver> argumentRes
118118
@Override
119119
public void extendMessageConverters(List<HttpMessageConverter<?>> converters) {
120120

121-
if (ClassUtils.isPresent("com.jayway.jsonpath.DocumentContext", context.getClassLoader())) {
121+
if (ClassUtils.isPresent("com.jayway.jsonpath.DocumentContext", context.getClassLoader())
122+
&& ClassUtils.isPresent("com.fasterxml.jackson.databind.ObjectMapper", context.getClassLoader())) {
122123

123124
ProjectingJackson2HttpMessageConverter converter = new ProjectingJackson2HttpMessageConverter(new ObjectMapper());
124125
converter.setBeanClassLoader(context.getClassLoader());
Lines changed: 200 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,200 @@
1+
/*
2+
* Copyright 2015-2017 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package org.springframework.data.web.config;
17+
18+
import static org.hamcrest.Matchers.*;
19+
import static org.junit.Assert.*;
20+
import static org.springframework.test.util.ReflectionTestUtils.*;
21+
22+
import java.net.URLClassLoader;
23+
import java.util.ArrayList;
24+
import java.util.List;
25+
import org.hamcrest.Matcher;
26+
import org.junit.Ignore;
27+
import org.junit.Test;
28+
import org.springframework.beans.BeansException;
29+
import org.springframework.beans.factory.ObjectFactory;
30+
import org.springframework.context.support.GenericApplicationContext;
31+
import org.springframework.core.convert.ConversionService;
32+
import org.springframework.data.web.ProjectingJackson2HttpMessageConverter;
33+
import org.springframework.data.web.XmlBeamHttpMessageConverter;
34+
import org.springframework.data.web.querydsl.QuerydslPredicateArgumentResolver;
35+
import org.springframework.http.converter.HttpMessageConverter;
36+
import org.springframework.instrument.classloading.ShadowingClassLoader;
37+
import org.springframework.web.context.support.GenericWebApplicationContext;
38+
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
39+
40+
/**
41+
* @author Christoph Strobl
42+
* @author Jens Schauder
43+
*/
44+
public class SpringDataWebConfigurationIntegrationTests {
45+
46+
@Test // DATACMNS-669
47+
public void shouldNotAddQuerydslPredicateArgumentResolverWhenQuerydslNotPresent() throws ClassNotFoundException,
48+
InstantiationException, IllegalAccessException {
49+
50+
ClassLoader classLoader = initClassLoader("com.mysema");
51+
52+
Object config = classLoader.loadClass(SpringDataWebConfiguration.class.getName())
53+
.newInstance();
54+
55+
setField(config, "context", classLoader.loadClass(GenericWebApplicationContext.class.getName()).newInstance()
56+
);
57+
setField(config, "conversionService", classLoader.loadClass(ObjectFactoryImpl.class.getName()).newInstance());
58+
59+
List<HandlerMethodArgumentResolver> argumentResolvers = new ArrayList<HandlerMethodArgumentResolver>();
60+
61+
invokeMethod(config, "addArgumentResolvers", argumentResolvers);
62+
63+
assertThat(argumentResolvers,
64+
not(hasItem((Matcher) instanceWithClassName(QuerydslPredicateArgumentResolver.class))));
65+
}
66+
67+
@Test // DATACMNS-669
68+
@Ignore("currently fails because he setup is not sufficient to trigger loading of the QuerydslArgumentResolver. See DATACMNS-993")
69+
public void shouldAddQuerydslPredicateArgumentResolverWhenQuerydslPresent() throws ClassNotFoundException,
70+
InstantiationException, IllegalAccessException {
71+
72+
ClassLoader classLoader = initClassLoader("load.everything");
73+
74+
Object config = classLoader.loadClass(SpringDataWebConfiguration.class.getName())
75+
.newInstance();
76+
77+
setField(config, "context", classLoader.loadClass(GenericWebApplicationContext.class.getName()).newInstance());
78+
setField(config, "conversionService", classLoader.loadClass(ObjectFactoryImpl.class.getName()).newInstance());
79+
80+
List<HandlerMethodArgumentResolver> argumentResolvers = new ArrayList<HandlerMethodArgumentResolver>();
81+
82+
invokeMethod(config, "addArgumentResolvers", argumentResolvers);
83+
84+
assertThat(argumentResolvers,
85+
hasItem((Matcher) instanceWithClassName(QuerydslPredicateArgumentResolver.class)));
86+
}
87+
88+
@Test // DATACOMNS-987
89+
public void shouldNotLoadJacksonConverterWhenJacksonNotPresent() {
90+
91+
SpringDataWebConfiguration config = createConfigWithClassLoaderExcluding("com.fasterxml.jackson");
92+
93+
List<HttpMessageConverter<?>> converters = new ArrayList<HttpMessageConverter<?>>();
94+
95+
config.extendMessageConverters(converters);
96+
97+
assertThat(converters, (Matcher) not(hasItem( //
98+
instanceWithClassName(ProjectingJackson2HttpMessageConverter.class))));
99+
}
100+
101+
@Test // DATACOMNS-987
102+
public void shouldNotLoadJacksonConverterWhenJaywayNotPresent() {
103+
104+
SpringDataWebConfiguration config = createConfigWithClassLoaderExcluding("com.jayway");
105+
106+
List<HttpMessageConverter<?>> converters = new ArrayList<HttpMessageConverter<?>>();
107+
108+
config.extendMessageConverters(converters);
109+
110+
assertThat(converters, (Matcher) not(hasItem( //
111+
instanceWithClassName(ProjectingJackson2HttpMessageConverter.class))));
112+
}
113+
114+
@Test // DATACOMNS-987
115+
public void shouldNotLoadXBeamConverterWhenXBeamNotPresent() throws ClassNotFoundException, IllegalAccessException, InstantiationException {
116+
117+
SpringDataWebConfiguration config = createConfigWithClassLoaderExcluding("org.xmlbeam");
118+
119+
List<HttpMessageConverter<?>> converters = new ArrayList<HttpMessageConverter<?>>();
120+
121+
config.extendMessageConverters(converters);
122+
123+
assertThat(converters, (Matcher) not(hasItem( //
124+
instanceWithClassName(XmlBeamHttpMessageConverter.class))));
125+
}
126+
127+
128+
@Test // DATACOMNS-987
129+
public void shouldLoadAllConvertersWhenDependenciesArePresent() throws ClassNotFoundException,
130+
IllegalAccessException, InstantiationException {
131+
132+
SpringDataWebConfiguration config = createConfigWithClassLoaderExcluding("load.everything");
133+
134+
List<HttpMessageConverter<?>> converters = new ArrayList<HttpMessageConverter<?>>();
135+
136+
config.extendMessageConverters(converters);
137+
138+
assertThat(converters, containsInAnyOrder( //
139+
instanceWithClassName(XmlBeamHttpMessageConverter.class), //
140+
instanceWithClassName(ProjectingJackson2HttpMessageConverter.class)));
141+
}
142+
143+
private SpringDataWebConfiguration createConfigWithClassLoaderExcluding(String excludedClassNamePrefix) {
144+
ClassLoader classLoader = initClassLoader(excludedClassNamePrefix);
145+
146+
SpringDataWebConfiguration config = new SpringDataWebConfiguration();
147+
GenericApplicationContext applicationContext = new GenericApplicationContext();
148+
applicationContext.setClassLoader(classLoader);
149+
150+
setField(config, "context", applicationContext);
151+
152+
return config;
153+
}
154+
155+
/**
156+
* creates a Matcher that check if an object is an instance of a class with the same name as the provided class.
157+
* This is necessary since we are dealing with multiple classloaders which would make a simple instanceof fail all
158+
* the time
159+
*
160+
* @param expectedClass the class that is expected (possibly loaded by a different classloader).
161+
* @return a Matcher
162+
*/
163+
private Matcher<Object> instanceWithClassName(Class<?> expectedClass) {
164+
return hasProperty("class", hasProperty("name", equalTo(expectedClass.getName())));
165+
}
166+
167+
private ClassLoader initClassLoader(final String excludedClassNamePrefix) {
168+
169+
return new ShadowingClassLoader(URLClassLoader.getSystemClassLoader()) {
170+
171+
@Override
172+
public Class<?> loadClass(String name) throws ClassNotFoundException {
173+
174+
if (name.startsWith(excludedClassNamePrefix)) {
175+
throw new ClassNotFoundException();
176+
}
177+
178+
return super.loadClass(name);
179+
}
180+
181+
@Override
182+
protected Class<?> findClass(String name) throws ClassNotFoundException {
183+
184+
if (name.startsWith(excludedClassNamePrefix)) {
185+
throw new ClassNotFoundException();
186+
}
187+
188+
return super.findClass(name);
189+
}
190+
};
191+
}
192+
193+
public static class ObjectFactoryImpl implements ObjectFactory<ConversionService> {
194+
195+
@Override
196+
public ConversionService getObject() throws BeansException {
197+
return null;
198+
}
199+
}
200+
}

src/test/java/org/springframework/data/web/config/SpringDataWebConfigurationUnitTests.java

Lines changed: 0 additions & 102 deletions
This file was deleted.

0 commit comments

Comments
 (0)