Browse Source

DATACMNS-1386 - Avoid strong type dependency to Jackson in SpringDataWebConfiguration.

We now avoid using a Lambda to provide a default ObjectMapper instance in the code that's reflectively guarded against Jackson not being present. The lambda causes a method to be generated for the class that will require ObjectMapper to be present on reflection inspection of that method. Switching to a method reference to ObjectMapper's constructor resolves that problem as the indirection via the additional, offending method is not needed.

Further reading: https://www.javabullets.com/how-lambdas-and-anonymous-inner-classesaic-work/
pull/310/merge
Oliver Gierke 7 years ago
parent
commit
8b6cc3af11
No known key found for this signature in database
GPG Key ID: 6E42B5787543F690
  1. 2
      src/main/java/org/springframework/data/web/config/SpringDataWebConfiguration.java
  2. 21
      src/test/java/org/springframework/data/web/config/SpringDataWebConfigurationIntegrationTests.java

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

@ -158,7 +158,7 @@ public class SpringDataWebConfiguration implements WebMvcConfigurer, BeanClassLo @@ -158,7 +158,7 @@ public class SpringDataWebConfiguration implements WebMvcConfigurer, BeanClassLo
if (ClassUtils.isPresent("com.jayway.jsonpath.DocumentContext", context.getClassLoader())
&& ClassUtils.isPresent("com.fasterxml.jackson.databind.ObjectMapper", context.getClassLoader())) {
ObjectMapper mapper = getUniqueBean(ObjectMapper.class, context, () -> new ObjectMapper());
ObjectMapper mapper = getUniqueBean(ObjectMapper.class, context, ObjectMapper::new);
ProjectingJackson2HttpMessageConverter converter = new ProjectingJackson2HttpMessageConverter(mapper);
converter.setBeanFactory(context);

21
src/test/java/org/springframework/data/web/config/SpringDataWebConfigurationIntegrationTests.java

@ -28,10 +28,12 @@ import org.springframework.context.annotation.AnnotationConfigApplicationContext @@ -28,10 +28,12 @@ import org.springframework.context.annotation.AnnotationConfigApplicationContext
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.classloadersupport.HidingClassLoader;
import org.springframework.data.classloadersupport.ShadowingClassLoader;
import org.springframework.data.web.ProjectingJackson2HttpMessageConverter;
import org.springframework.data.web.XmlBeamHttpMessageConverter;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.test.util.ReflectionTestUtils;
import org.springframework.util.ReflectionUtils;
import org.xmlbeam.XBProjector;
import com.fasterxml.jackson.databind.ObjectMapper;
@ -108,8 +110,13 @@ public class SpringDataWebConfigurationIntegrationTests { @@ -108,8 +110,13 @@ public class SpringDataWebConfigurationIntegrationTests {
}, SomeConfiguration.class);
}
private void createConfigWithClassLoader(ClassLoader classLoader, Consumer<SpringDataWebConfiguration> callback,
Class<?>... additionalConfigurationClasses) {
@Test // DATACMNS-1386
public void doesNotFailWithJacksonMissing() throws Exception {
ReflectionUtils.getUniqueDeclaredMethods(loadWithout(SpringDataWebConfiguration.class, ObjectMapper.class));
}
private static void createConfigWithClassLoader(ClassLoader classLoader,
Consumer<SpringDataWebConfiguration> callback, Class<?>... additionalConfigurationClasses) {
List<Class<?>> configClasses = new ArrayList<>(Arrays.asList(additionalConfigurationClasses));
configClasses.add(SpringDataWebConfiguration.class);
@ -122,6 +129,16 @@ public class SpringDataWebConfigurationIntegrationTests { @@ -122,6 +129,16 @@ public class SpringDataWebConfigurationIntegrationTests {
}
}
private static Class<?> loadWithout(Class<?> configurationClass, Class<?>... typesOfPackagesToExclude)
throws ClassNotFoundException {
HidingClassLoader hidingClassLoader = HidingClassLoader.hide(typesOfPackagesToExclude);
ShadowingClassLoader loader = new ShadowingClassLoader(hidingClassLoader);
loader.excludeClass(configurationClass.getName());
return loader.loadClass(configurationClass.getName());
}
/**
* Creates a {@link Condition} that checks if an object is an instance of a class with the same name as the provided
* class. This is necessary since we are dealing with multiple classloaders which would make a simple instanceof fail

Loading…
Cancel
Save