2009-02-14 16 views
5

Soy nuevo en portillo y estaba tratando la siguiente configuración:Wicket PropertyModel strangeness?

class User { 
    private String password; 

    ... 

    public void setPassword(String password) { 
    this.password = MD5.encode(password); 
    } 
    ... 
} 

Después de tratar de usar lo siguiente para unirse a la contraseña y descubrir que la implementación predeterminada de PropertyModel es por defecto a dependiente del campo , no la propiedad (nombre raro eh?)

add(new PasswordTextField("password", new PropertyModel(user, "password")); 

¿por qué en el mundo se han puesto en práctica esta manera? ¿Y hay una alternativa de PropertyModel que use getter y setters por defecto?

Gracias?

Respuesta

11

PropertyModel hará lo que usted ya quiere. Cuando un PropertyModel se consulta por su valor, se ve en dos lugares:

  • Si existe un método "getter" para la propiedad dada, la PropertyModel llama al comprador para recuperar el valor de la propiedad. Específicamente, el PropertyModel busca un método denominado get<Property>, donde <Property> es la expresión de propiedad que se pasa al constructor PropertyModel, y llama al método utilizando el reflejo si existe.

  • Si no existe el método "getter", el PropertyModel devuelve el valor del campo de propiedad directamente. Específicamente, el PropertyModel utiliza reflexión para encontrar un campo que coincida con la expresión de propiedad pasada al constructor PropertyModel. Si se encuentra un campo coincidente, el PropertyModel devuelve el valor del campo. Tenga en cuenta que PropertyModel comprobará los campos privados y protegidos además de los campos públicos para una coincidencia.

En su caso, la expresión bienes utilizados en el PropertyModel constructor es "password", por lo que el PropertyModel buscará primero un método en el objeto user llamada getPassword. Si no existe tal método, el PropertyModel devolverá el valor del campo privado password en su lugar.

Dado que en su caso el PropertyModel está devolviendo el valor del campo privado en lugar de llamar al "captador", es muy probable que haya escrito mal el nombre del captador en su clase User. Por ejemplo, si accidentalmente ingresó getPasssword (con 3 s), el PropertyModel no lo encontrará, y recurrirá a devolver el campo privado.


EDITAR

Si no te gusta el comportamiento predeterminado PropertyModel 's, se puede crear una subclase de PropertyModel que evitará Wicket de tratar de leer/escribir en campos privados. De esta forma, puede forzar todos los accesos a propiedades a través de getters y setters.

me escribió un ejemplo BeanPropertyModel clase para demostrar esto:

import org.apache.wicket.WicketRuntimeException; 
import org.apache.wicket.model.PropertyModel; 

/** 
* A custom implementation of {@link org.apache.wicket.model.PropertyModel} 
* that can only be bound to properties that have a public getter or setter method. 
* 
* @author mspross 
* 
*/ 
public class BeanPropertyModel extends PropertyModel { 

    public BeanPropertyModel(Object modelObject, String expression) { 
     super(modelObject, expression); 
    } 

    @Override 
    public Object getObject() { 
     if(getPropertyGetter() == null) 
      fail("Missing getter"); 
     return super.getObject();    
    } 

    @Override 
    public void setObject(Object modelObject) { 
     if(getPropertySetter() == null) 
      fail("Missing setter"); 
     super.setObject(modelObject); 
    } 

    private void fail(String message) { 

     throw new WicketRuntimeException(
       String.format("%s. Property expression: '%s', class: '%s'.", 
         message, 
         getPropertyExpression(), 
         getTarget().getClass().getCanonicalName())); 
    } 
} 
+0

¡Excelente respuesta! Muchas gracias por aclararlo. –

+0

Lo que he estado haciendo no fue proporcionar un getter y espero que sea llamar al setter. Motivo: no quería que el usuario objetara tener un método getPassword(). –

+0

Todavía llamará al colocador, ya que definió uno, pero cuando Wicket presente el campo de contraseña, intentará "obtener" el valor del modelo y terminará recuperando el campo privado. Si desea evitar esto, puede anular getObject() para devolver nulo o una cadena de caracteres "*", o lo que sea. –

3

gran respuesta de Mike Spross! aunque una pequeña adición:

No utilizaría el modelo de propiedad en este caso. simplemente escriba

new Model<String>(){ getObject(){...} setObject(){...}} 

e implemente el comportamiento correcto, que hace exactamente lo que desea.

+1

+1 - Si se trata de una operación "única", esta es la forma más fácil de obtener la funcionalidad necesaria. –