[
https://issues.apache.org/jira/browse/FREEMARKER-183?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=17748976#comment-17748976
]
Simon commented on FREEMARKER-183:
----------------------------------
It seems to work if I add this to the end of
ClassIntrospector.addBeanInfoToClassIntrospectionData:
{code:java}
if (isRecordType(clazz)) {
Method[] accessors = RecordAccessor.instance().getAccessors(clazz);
for (Method accessor : accessors) {
if (effClassMemberAccessPolicy.isMethodExposed(accessor)) {
introspData.put(accessor.getName(), new
FastPropertyDescriptor(accessor, null));
}
}
}{code}
We have this at the end so that it overwrites this having been found as a
method first.
Because it's now defined as a property, you can no longer invoke it as a method.
isRecordType:
{code:java}
private static boolean isRecordType(Class<?> clazz) {
Class<?> parent = clazz.getSuperclass();
return (parent != null) && "java.lang.Record".equals(parent.getName());
}{code}
RecordAccessor:
{code:java}
public class RecordAccessor {
private final Method RECORD_GET_RECORD_COMPONENTS;
private final Method RECORD_COMPONENT_GET_ACCESSOR;
private final static RecordAccessor INSTANCE;
private final static RuntimeException PROBLEM;
static {
RuntimeException prob = null;
RecordAccessor inst = null;
try {
inst = new RecordAccessor();
} catch (RuntimeException e) {
prob = e;
}
INSTANCE = inst;
PROBLEM = prob;
}
private RecordAccessor() throws RuntimeException {
try {
RECORD_GET_RECORD_COMPONENTS =
Class.class.getMethod("getRecordComponents");
Class<?> c = Class.forName("java.lang.reflect.RecordComponent");
RECORD_COMPONENT_GET_ACCESSOR = c.getMethod("getAccessor");
} catch (Exception e) {
throw new RuntimeException(String.format(
"Failed to access Methods needed to support
`java.lang.Record`: (%s) %s",
e.getClass().getName(), e.getMessage()), e);
}
}
public static RecordAccessor instance() {
if (PROBLEM != null) {
throw PROBLEM;
}
return INSTANCE;
}
private Object[] recordComponents(Class<?> recordType) throws
IllegalArgumentException {
try {
return (Object[]) RECORD_GET_RECORD_COMPONENTS.invoke(recordType);
} catch (Exception e) {
throw new IllegalArgumentException("Failed to access
RecordComponents of type "
+ recordType.getName());
}
}
public Method[] getAccessors(Class<?> recordType) throws
IllegalArgumentException {
final Object[] components = recordComponents(recordType);
if (components == null) {
// not a record, or no reflective access on native image
return null;
}
final Method[] accessors = new Method[components.length];
for (int i = 0; i < components.length; i++) {
try {
accessors[i] = (Method)
RECORD_COMPONENT_GET_ACCESSOR.invoke(components[i]);
} catch (Exception e) {
throw new IllegalArgumentException(String.format(
"Failed to access name of field #%d (of %d) of Record
type %s",
i, components.length, recordType.getName()), e);
}
}
return accessors;
}
}{code}
> Add support for Java records
> ----------------------------
>
> Key: FREEMARKER-183
> URL: https://issues.apache.org/jira/browse/FREEMARKER-183
> Project: Apache Freemarker
> Issue Type: Task
> Reporter: Dániel Dékány
> Assignee: Dániel Dékány
> Priority: Major
>
> Currently we don't support records (JEP 395), which was finalized in Java 16.
> Users can extend {{DefaultObjectWrapper}} for that of course, but it should
> be supported out of the box.
--
This message was sent by Atlassian Jira
(v8.20.10#820010)