eclipse-ee4j / glassfish

Eclipse GlassFish
https://eclipse-ee4j.github.io/glassfish/
377 stars 143 forks source link

Can not access Record via property in EL #25052

Open hantsy opened 1 month ago

hantsy commented 1 month ago

Environment Details


Problem Description

EL 6.0 supports record, but I have tried in a simple facelets page, failed to access the property.

...faces-examples/customer.xhtml: The class 'com.example.Customer' 
does not have the property 'firstName'.

The example project: https://github.com/hantsy/jakartaee11-sandbox/tree/master/faces

The back bean:

@RequestScoped
@Named
public class CustomerBean {
    private final static Logger LOGGER= Logger.getLogger(CustomerBean.class.getName());

    @Inject
    FacesContext facesContext;

    private Customer customer;

    public Customer getCustomer() {
        return customer;
    }

    //@PostConstruct
    // use faces event to initialize it
    public void init(PreRenderViewEvent event) {
        if(facesContext.isPostback()){
            LOGGER.log(Level.INFO, "postback, skipping initialization");
            return;
        }

        LOGGER.log(Level.INFO, "initializing");
        customer = new Customer(
                "Foo",
                "Bar",
                new EmailAddress[]{
                        new EmailAddress("foo@example.com", true),
                        new EmailAddress("bar@example.com", false)
                },
                new Address("123 Main St", "Anytown", "CA", "12345")
        );
        LOGGER.log(Level.INFO, "initialized");
    }
}

public record Customer(
        String firstName,
        String lastName,
        EmailAddress[] emailAddresses,
        Address address
) {
}
record EmailAddress(
        String email,
        Boolean primary
) {
}
record Address(
        String street,
        String city,
        String state,
        String zipCode
) {
}

The facelets template:

<!DOCTYPE html>
<html lang="en"
      xmlns="http://www.w3.org/1999/xhtml"
      xmlns:ui="jakarta.faces.facelets"
      xmlns:f="jakarta.faces.core"
      xmlns:h="jakarta.faces.html">
<f:view>
    <f:metadata>
        <f:event listener="#{customerBean.init}" type="preRenderView"/>
    </f:metadata>
    <h:head>
        <title>Express Language 6.0!</title>
    </h:head>
    <h:body>
        <h1>Express Language 6.0</h1>

        <div>
            <strong>#{customerBean.customer.firstName +' ' +customerBean.customer.lastName}</strong>
            <hr/>
        </div>
        <div>Emails: (#{customerBean.customer.emailAddresses.length})</div>
        <ul>
            <ui:repeat value="#{customerBean.customer.emailAddresses}" var="email">
                <li>#{email.email}(#{email.primary?'O':'X'})</li>
            </ui:repeat>
        </ul>
        <div>
            #{customerBean.customer.address.street},
            #{customerBean.customer.address.city},
            #{customerBean.customer.address.state},
            #{customerBean.customer.address.zipCode},
        </div>
    </h:body>
</f:view>
</html>
arjantijms commented 1 month ago

As a quick test, within GF (in a servlet, bean, whatever) you could try invoking Expression Language "manually" (using the universal Java SE way) to see if records work. Normally the RecordELResolver should be added just before the BeanELResolver.

Start with

ELProcessor elProcessor = new ELProcessor();

And then work with that on your types (just as a smoke test)

Tbh, I did not take a look whether extra setup is required in Mojarra. There probably is.

hantsy commented 1 month ago

@arjantijms Tried it in a separate project, worked well.

https://github.com/hantsy/jakartaee11-sandbox/blob/master/el/src/main/java/com/example/ELExample.java

arjantijms commented 1 month ago

Thank you very much, so the API and optionally perhaps Expressly works correct here.

I'll have to figure out where to add it in mojarra

hantsy commented 1 month ago

@arjantijms Still failed in Glassfish 8.0.0-M7

arjantijms commented 4 weeks ago

@hantsy the following line in your example will crash any way:

<strong>#{customerBean.customer.firstName +' ' +customerBean.customer.lastName}</strong>

Removing that and with the latest 4.1.2-SNAPSHOT it does seem to work.

faces_el6

https://github.com/eclipse-ee4j/mojarra/pull/5481

OndroMih commented 3 weeks ago

In <strong>#{customerBean.customer.firstName +' ' +customerBean.customer.lastName}</strong>, plain + should be replaced with +=, which is an operator for string concatenation. Then it should work. Plain + only works with numbers.

hantsy commented 3 weeks ago

Sorry, I forgot to update this. But here it indicated some info similar to can not access property customer.firstName, so I thought the EL resolver for record was still not applied.

arjantijms commented 2 weeks ago

@hantsy If you want to try again, this binary https://ci.eclipse.org/glassfish/job/glassfish_build-and-test-using-jenkinsfile/job/PR-25108/1/artifact/bundles/glassfish.zip includes the updated Mojarra 4.1.2.