[ 
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)

Reply via email to