Java 8 default interface methods not recognized as

2019-02-17 09:12发布

问题:

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?

回答1:

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()}


回答2:

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.