Java 8 default interface methods not recognized as managed bean properties in EL
Asked Answered
Q

2

6

I am trying to setup my own JSF tag libary. So I created a composite component with an backing interfaces as a blueprint to build a backing bean for this component.

public interface CompLogin {
   String getUsername();
   void setUsername(String username);

   String getPassword();
   void setPassword(String password);

   String validateLogin();

   default String getPasswordWatermark() {
      return "Passwort";
   }

   default String getUsernameWatermark() {
      return "Loginname:";
   }

   default String getLoginButtonValue() {
      return "Login";
   }
}

So I have Password, Username and an Validate method for a Login site. Additionally O want serve some default namings for Inputtext watermarks and the Button. If the implementing person want to change it, he could.

I implemented this interface inside a Backing bean of a real application using my own JSF tag.

@Named
@RequestScoped
public class Login implements Serializable, CompLogin {

    private String username;
    private String password;


    @Override
    public String getUsername() {
        return username;
    }

    @Override
    public void setUsername(String username) {
        this.username = username;
    }

    @Override
    public String getPassword() {
        return password;
    }

    @Override
    public void setPassword(String password) {
        this.password = password;
    }

    @Override
    public String validateLogin() {
        System.out.println(username + " " + password);
        return null;
    }
}

I tought it could work this way. But I get the error: 'Caused by: javax.el.PropertyNotFoundException: The class 'Login' does not have the property 'usernameWatermark'.'

It seems like the default implementation of the interface is not inherited in my implementing bean. Why and what could I do to serve default implementations for my components?

Edit: I tried the following to ommit a missunderstanding of the interface default method conecpt. I took my interface and der implementing class in a normal java project tried to access the getLoginButtonValue thru the Login class.

public class Main {

    public static void main(String[] args) {
        Login log = new Login();
        System.out.println(log.getLoginButtonValue());
    }
}

Works very well. The correct String got printed out. There is no need to implement the default methods to access them. So where is the problem? Maybe there is something like cdi, bean-resolver or somthing else not aware of this java 8 concept?

Qualify answered 13/5, 2016 at 9:0 Comment(4)
What JSF library are you using?Ingeborgingelbert
@BalusC I was thinking that it might be a problem of the library being slightly old, and that its reflection logic does not take Java 8 interface methods into account to determine the available properties, but, hey, since you're here now, I'll move along to greener pastures.Ingeborgingelbert
The testimplementation for the tag libary runs on jsf 2.2 in a wildfly 10 final.Qualify
Hm just tested it in a normal java 8 enviroment. Maybe there is a problem in jsf or cdi?Qualify
M
5

Working with Apache EL this works by calling the default method by its full name. Try to use it this way in your code:

#{login.getUsernameWatermark()}
Muckraker answered 30/5, 2017 at 9:28 Comment(1)
See developer.jboss.org/message/986179 for another answer, vote for EL bug issues.jboss.org/browse/JBEE-159 because the workaround described here doesn't work at all times (blocker).Hardandfast
H
1

The problem is likely caused by EL relying on reflection to find the appropriate accessor methods, but doing it in a way that fails for default methods.

Consider implementing a custom ELResolver similar to what they did here.

Heterotypic answered 10/4, 2017 at 10:56 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.