How can I bring Wicket 7 to work with java.time fr

2019-05-04 07:12发布

I have lots of beans and all use LocalDate and LocalDateTime. The DateTextField in Wicket and all other widgets (like the DatePicker) only work on java.util.Date. Is there any way to inject a converter into Wicket 7 so that it uses LocalDate or LocalDateTime?

The beans look like this:

public class SomeBean {
  Long id = null;
  LocalDate since = null;
  // plus getters and setters
}

A Wicket form currently uses a CompoundPropertyModel

CompoundPropertyModel<SomeBean> model = new CompundPropertyModel<>( bean );

3条回答
smile是对你的礼貌
2楼-- · 2019-05-04 07:40

You can register your own converters:

https://ci.apache.org/projects/wicket/guide/7.x/guide/forms2.html#forms2_3

@Override
protected IConverterLocator newConverterLocator() {
    ConverterLocator defaultLocator = new ConverterLocator();

    defaultLocator.set(Pattern.class, new RegExpPatternConverter());

    return defaultLocator;
}

Related: https://issues.apache.org/jira/browse/WICKET-6200

查看更多
戒情不戒烟
3楼-- · 2019-05-04 07:41

You can wrap your LocalDate and etc. models in a IModel<java.util.Date>, e.g.

public static class LocalDateModel implements IModel<java.util.Date> {
    private IModel<LocalDate> localDateModel;
    public LocalDateModel(IModel<LocalDate> localDateModel){
        this.localDateModel = localDateModel;
    }


    @Override
    public Date getObject() {
        return convertLocalDateToUtilDateSomehow(localDateModel.getObject());
    }

    @Override
    public void setObject(Date object) {
        localDateModel.setObject(convertUtilDateToLocalDateSomehow(object));
    }

    @Override
    public void detach() {
        localDateModel.detach();
    }
}

If you then feed models like this into the form components you want to use it should work just fine.

If you want your CompoundPropertyModel to automatically provide such wrapping models, you need to extend it and override it's CompoundPropertyModel#wrapOnInheritance(Component component) method to infer that a wrapping model is needed. Something like

@Override
public <C> IWrapModel<C> wrapOnInheritance(Component component)
{
    IWrapModel<C> actualModel = super.wrapOnInheritance(component);
    if (actualModel.getObject() instanceOf LocalDate) {
        return new LocalDateModelButAlsoWrapping(actualModel);
    } else {
        return actualModel;
    }
}

Where LocalDateModelButAlsoWrapping is unsurprisingly just an extension of LocalDateModel example above but which also implements IWrapModel<T>.

If you use this extension instead of your regular CompoundPropertyModel it would detect when fields are LocalDate and provide models to components (like your DateTextField) that are wrapped to look like java.util.Date models.

The code snippet I gave you is rather dirty though (you should probably not get the model object to infer its type) as I have only provided it to illustrate the general mechanism, so I suggest you devise your own way to infer the type of object expected (e.g. you can check if the Component argument is a DateTextField), but this is the general direction of the solution that I can imagine.

查看更多
神经病院院长
4楼-- · 2019-05-04 07:59

You can simply backport the converter classes from Wicket 8. You'll find these attached to this commit: https://issues.apache.org/jira/browse/WICKET-6200 (AbstractJavaTimeConverter and whatever subclasses you need for LocalDate, LocalDateTime, LocalTime, etc.)

Of course, that will not help with a DateTextField, because that has the Date type parameter hardcoded. For such, you can either create your own subclasses using the above converters, or use regular Label and TextField, with converters registered globally, as shown below:

@Override
protected IConverterLocator newConverterLocator() {
    ConverterLocator converterLocator = new ConverterLocator();
    converterLocator.set(LocalDateTime.class, new LocalDateTimeConverter());
    converterLocator.set(LocalDate.class, new LocalDateConverter());
    converterLocator.set(LocalTime.class, new LocalDateConverter());
    return converterLocator;
}
查看更多
登录 后发表回答