Current workaround, ugly as hell but will fix it for me until this is corrected:
package be.valuya.gestemps.server;
import be.valuya.gestemps.util.DomainObject;
import java.beans.BeanInfo;
import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import javax.interceptor.AroundInvoke;
import javax.interceptor.InvocationContext;
/**
*
* @author Yannick
*/
public class ProxiedEntityInterceptor {
@AroundInvoke
public Object removeProxy(InvocationContext invocationContext) throws Exception {
Object[] parameters = invocationContext.getParameters();
if (parameters != null) {
Object[] filteredParameters = Stream.of(parameters)
.map(this::getRealDomainObject)
.collect(Collectors.toList())
.toArray(new Object[0]);
invocationContext.setParameters(filteredParameters);
}
return invocationContext.proceed();
}
private Object getRealDomainObject(Object sourceObject) {
Map<Object, Object> filteredObjectMap = new HashMap<>();
return getRealDomainObject(filteredObjectMap, sourceObject);
}
private Object getRealDomainObject(Map<Object, Object> filteredObjectMap, Object sourceObject) {
if (!(sourceObject instanceof DomainObject)) { // some shortcut that works in my case, remove or adapt if you don't want to filter every parameter
return sourceObject;
}
if (filteredObjectMap.containsKey(sourceObject)) {
return filteredObjectMap.get(sourceObject);
}
try {
Class<?> sourceClass = sourceObject.getClass();
String sourceClassName = sourceClass.getName();
Pattern proxyPattern = Pattern.compile("^(.*)\\$Proxy.*$");
Matcher matcher = proxyPattern.matcher(sourceClassName);
Class targetClass;
if (matcher.matches()) {
String unproxiedClassName = matcher.group(1);
try {
targetClass = Class.forName(unproxiedClassName);
} catch (ClassNotFoundException classNotFoundException) {
throw new IllegalStateException(classNotFoundException);
}
} else {
targetClass = sourceClass;
}
Object targetObject = targetClass.newInstance();
filteredObjectMap.put(sourceObject, targetObject);
BeanInfo beanInfo = Introspector.getBeanInfo(targetClass);
PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors();
for (PropertyDescriptor propertyDescriptor : propertyDescriptors) {
Method readMethod = propertyDescriptor.getReadMethod();
Method writeMethod = propertyDescriptor.getWriteMethod();
if (writeMethod == null) {
// e.g. getClass() has no setter...
continue;
}
Object value = readMethod.invoke(sourceObject);
Object filteredValue = getRealDomainObject(filteredObjectMap, value);
writeMethod.invoke(targetObject, filteredValue);
}
return targetObject;
} catch (IllegalArgumentException | IntrospectionException | InvocationTargetException | IllegalAccessException | InstantiationException exception) {
throw new RuntimeException(exception);
}
}
}