package com.exteso.lab.pf.config.reload.reloader; import com.fasterxml.jackson.databind.DeserializationContext; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.SerializerProvider; import com.fasterxml.jackson.databind.deser.DeserializerCache; import com.fasterxml.jackson.databind.ser.SerializerCache; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.BeanFactoryUtils; import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; import org.springframework.context.ConfigurableApplicationContext; import org.springframework.core.annotation.AnnotationUtils; import org.springframework.util.ReflectionUtils; import javax.persistence.Entity; import java.lang.annotation.Annotation; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.util.Collection; /** * Reloads Jackson classes. */ public class JacksonReloader { private final Logger log = LoggerFactory.getLogger(JacksonReloader.class); private ConfigurableApplicationContext applicationContext; public JacksonReloader(ConfigurableApplicationContext applicationContext) { log.debug("Hot reloading Jackson enabled"); this.applicationContext = applicationContext; } public void reloadEvent() { log.debug("Hot reloading Jackson classes"); try { ConfigurableListableBeanFactory beanFactory = applicationContext.getBeanFactory(); Collection<ObjectMapper> mappers = BeanFactoryUtils .beansOfTypeIncludingAncestors(beanFactory, ObjectMapper.class) .values(); for (ObjectMapper mapper : mappers) { log.trace("Flushing Jackson serializer cache"); SerializerProvider serializerProvider = mapper.getSerializerProvider(); Field serializerCacheField = serializerProvider.getClass().getSuperclass().getSuperclass().getDeclaredField("_serializerCache"); ReflectionUtils.makeAccessible(serializerCacheField); SerializerCache serializerCache = (SerializerCache) serializerCacheField.get(serializerProvider); Method serializerCacheFlushMethod = SerializerCache.class.getDeclaredMethod("flush"); serializerCacheFlushMethod.invoke(serializerCache); log.trace("Flushing Jackson deserializer cache"); DeserializationContext deserializationContext = mapper.getDeserializationContext(); Field deSerializerCacheField = deserializationContext.getClass().getSuperclass().getSuperclass().getDeclaredField("_cache"); ReflectionUtils.makeAccessible(deSerializerCacheField); DeserializerCache deSerializerCache = (DeserializerCache) deSerializerCacheField.get(deserializationContext); Method deSerializerCacheFlushMethod = DeserializerCache.class.getDeclaredMethod("flushCachedDeserializers"); deSerializerCacheFlushMethod.invoke(deSerializerCache); } } catch (Exception e) { log.warn("Could not hot reload Jackson class!"); e.printStackTrace(); } } }