Use a different approach to disable HATEOAS Objenesis instance's cache
Previously, reflection was used to set the OBJENESIS field of DummyInvocationUtils with an Objenesis instance that does not use caching. This has stopped working as the field is now declared final. This commit updates the approach take by HateoasObjenesisCacheDisabler to disable Objenesis's cache. Rather than changing the value of the OBJENESIS field on DummyInvocationUtils, the cache field on the ObjenesisStd instance is set to null instead. This has the desired effect of disabling Objenesis's caching. See gh-3784 Closes gh-8335
This commit is contained in:
parent
d1184bf180
commit
627edc0f7a
|
|
@ -127,6 +127,11 @@
|
|||
<artifactId>spring-websocket</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.hateoas</groupId>
|
||||
<artifactId>spring-hateoas</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.tomcat.embed</groupId>
|
||||
<artifactId>tomcat-embed-websocket</artifactId>
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2012-2015 the original author or authors.
|
||||
* Copyright 2012-2017 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
|
@ -20,7 +20,9 @@ import java.lang.reflect.Field;
|
|||
|
||||
import javax.annotation.PostConstruct;
|
||||
|
||||
import org.springframework.objenesis.ObjenesisStd;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import org.springframework.util.ClassUtils;
|
||||
import org.springframework.util.ReflectionUtils;
|
||||
|
||||
|
|
@ -35,6 +37,9 @@ import org.springframework.util.ReflectionUtils;
|
|||
*/
|
||||
class HateoasObjenesisCacheDisabler {
|
||||
|
||||
private static final Log logger = LogFactory
|
||||
.getLog(HateoasObjenesisCacheDisabler.class);
|
||||
|
||||
private static boolean cacheDisabled;
|
||||
|
||||
@PostConstruct
|
||||
|
|
@ -45,20 +50,36 @@ class HateoasObjenesisCacheDisabler {
|
|||
}
|
||||
}
|
||||
|
||||
private void doDisableCaching() {
|
||||
void doDisableCaching() {
|
||||
try {
|
||||
Class<?> type = ClassUtils.forName(
|
||||
"org.springframework.hateoas.core.DummyInvocationUtils",
|
||||
getClass().getClassLoader());
|
||||
Field objenesis = ReflectionUtils.findField(type, "OBJENESIS");
|
||||
if (objenesis != null) {
|
||||
ReflectionUtils.makeAccessible(objenesis);
|
||||
ReflectionUtils.setField(objenesis, null, new ObjenesisStd(false));
|
||||
}
|
||||
removeObjenesisCache(type);
|
||||
}
|
||||
catch (Exception ex) {
|
||||
// Assume that Spring HATEOAS is not on the classpath and continue
|
||||
}
|
||||
}
|
||||
|
||||
private void removeObjenesisCache(Class<?> dummyInvocationUtils) {
|
||||
try {
|
||||
Field objenesisField = ReflectionUtils.findField(dummyInvocationUtils,
|
||||
"OBJENESIS");
|
||||
if (objenesisField != null) {
|
||||
ReflectionUtils.makeAccessible(objenesisField);
|
||||
Object objenesis = ReflectionUtils.getField(objenesisField, null);
|
||||
Field cacheField = ReflectionUtils.findField(objenesis.getClass(),
|
||||
"cache");
|
||||
ReflectionUtils.makeAccessible(cacheField);
|
||||
ReflectionUtils.setField(cacheField, objenesis, null);
|
||||
}
|
||||
}
|
||||
catch (Exception ex) {
|
||||
logger.warn(
|
||||
"Failed to disable Spring HATEOAS's Objenesis cache. ClassCastExceptions may occur",
|
||||
ex);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,67 @@
|
|||
/*
|
||||
* Copyright 2012-2017 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.boot.devtools.autoconfigure;
|
||||
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.hateoas.core.DummyInvocationUtils;
|
||||
import org.springframework.objenesis.ObjenesisStd;
|
||||
import org.springframework.objenesis.instantiator.ObjectInstantiator;
|
||||
import org.springframework.test.util.ReflectionTestUtils;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
/**
|
||||
* Tests for {@link HateoasObjenesisCacheDisabler}.
|
||||
*
|
||||
* @author Andy Wilkinson
|
||||
*/
|
||||
public class HateoasObjenesisCacheDisablerTests {
|
||||
|
||||
private ObjenesisStd objenesis;
|
||||
|
||||
@Before
|
||||
@After
|
||||
public void resetCacheField() {
|
||||
this.objenesis = (ObjenesisStd) ReflectionTestUtils
|
||||
.getField(DummyInvocationUtils.class, "OBJENESIS");
|
||||
ReflectionTestUtils.setField(this.objenesis, "cache",
|
||||
new ConcurrentHashMap<String, ObjectInstantiator<?>>());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void cacheIsEnabledByDefault() {
|
||||
assertThat(this.objenesis.getInstantiatorOf(TestObject.class))
|
||||
.isSameAs(this.objenesis.getInstantiatorOf(TestObject.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void cacheIsDisabled() {
|
||||
new HateoasObjenesisCacheDisabler().doDisableCaching();
|
||||
assertThat(this.objenesis.getInstantiatorOf(TestObject.class))
|
||||
.isNotSameAs(this.objenesis.getInstantiatorOf(TestObject.class));
|
||||
}
|
||||
|
||||
private static class TestObject {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
Loading…
Reference in New Issue