2016-06-27 3 views
1

「Learning Vaadin 7、Second Edition」という本の後、今では単純な豆をテーブルに表示しようとしています。ただし、このマニュアルでは、古いjava.util.Dateクラスの使用方法についてのみ説明しています。私は、コンバータを使用してLocalDateプロパティを表示しようとしています。Vaadinテーブルの文字列をLocalDateに設定する

豆(人)私は、ディスプレイにしようとしています:

public class Person { 

private long id; 
private String firstName; 
private String lastName; 
private LocalDate birthdate; 
private Gender gender; 

// .. GETTERS & SETTERS 

私はcom.vaadin.data.util.converter.Converterを実装し、LocalDateToStringConverterを書かれています。私はいくつかの例のPersonオブジェクトを入れているBeanItemContainerを、という

... 
Table table = new Table("", container); 
table.setConverter("birthdate", new LocalDateToStringConverter()); 

verticalLayout.addComponent(table); 

「コンテナ」:UIで

package be.kapture.converters; 

import com.vaadin.data.util.converter.Converter; 

import java.time.LocalDate; 
import java.time.format.DateTimeFormatter; 
import java.time.format.DateTimeParseException; 
import java.util.Locale; 

public class LocalDateToStringConverter implements Converter<String, LocalDate> { 

    @Override 
    public LocalDate convertToModel(String value, Class<? extends LocalDate> targetType, Locale locale) throws ConversionException { 
     DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd-MM-yyyy"); 
     try { 
      return LocalDate.parse(value, formatter); 

     } catch (DateTimeParseException ex) { 
      return null; 
     } 
    } 

    @Override 
    public String convertToPresentation(LocalDate value, Class<? extends String> targetType, Locale locale) throws ConversionException { 
     return value.toString(); 
    } 

    @Override 
    public Class<LocalDate> getModelType() { 
     return LocalDate.class; 
    } 

    @Override 
    public Class<String> getPresentationType() { 
     return String.class; 
    } 
} 

は、ここで私は、コンバータを設定するコードスニペットです。私のブラウザでVaadinアプリケーションを訪問したとき 私は次の例外を取得:

jun 27, 2016 1:56:45 PM org.apache.catalina.core.StandardWrapperValve invoke 
SEVERE: Servlet.service() for servlet [HelloVaadinServlet] in context with path [] threw exception [com.vaadin.server.ServiceException: com.vaadin.ui.Table$CacheUpdateException: Error during Table cache update. Additional causes not shown.] with root cause 
com.vaadin.data.util.converter.Converter$ConversionException: Unable to convert value of type java.time.LocalDate to presentation type class java.lang.String. No converter is set and the types are not compatible. 
    at com.vaadin.data.util.converter.ConverterUtil.convertFromModel(ConverterUtil.java:116) 
    at com.vaadin.ui.AbstractField.convertFromModel(AbstractField.java:736) 
    at com.vaadin.ui.AbstractField.convertFromModel(AbstractField.java:721) 
    at com.vaadin.ui.AbstractField.setPropertyDataSource(AbstractField.java:657) 
    at com.vaadin.ui.Table.bindPropertyToField(Table.java:4140) 
    at com.vaadin.ui.Table.getPropertyValue(Table.java:4109) 
    at com.vaadin.ui.Table.parseItemIdToCells(Table.java:2386) 
    at com.vaadin.ui.Table.getVisibleCellsNoCache(Table.java:2225) 
    at com.vaadin.ui.Table.refreshRenderedCells(Table.java:1745) 
    at com.vaadin.ui.Table.refreshRowCache(Table.java:2691) 
    at com.vaadin.ui.Table.containerItemSetChange(Table.java:4587) 
    at com.vaadin.data.util.AbstractContainer.fireItemSetChange(AbstractContainer.java:242) 
    at com.vaadin.data.util.AbstractInMemoryContainer.fireItemsAdded(AbstractInMemoryContainer.java:1012) 
    at com.vaadin.data.util.AbstractInMemoryContainer.fireItemAdded(AbstractInMemoryContainer.java:994) 
    at com.vaadin.data.util.AbstractInMemoryContainer.internalAddItemAtEnd(AbstractInMemoryContainer.java:884) 
    at com.vaadin.data.util.AbstractBeanContainer.addItem(AbstractBeanContainer.java:533) 
    at com.vaadin.data.util.AbstractBeanContainer.addBean(AbstractBeanContainer.java:598) 
    at com.vaadin.data.util.BeanItemContainer.addItem(BeanItemContainer.java:227) 
    at be.kapture.MyUI.init(MyUI.java:88) 
    at com.vaadin.ui.UI.doInit(UI.java:682) 
    at com.vaadin.server.communication.UIInitHandler.getBrowserDetailsUI(UIInitHandler.java:214) 
    at com.vaadin.server.communication.UIInitHandler.synchronizedHandleRequest(UIInitHandler.java:74) 
    at com.vaadin.server.SynchronizedRequestHandler.handleRequest(SynchronizedRequestHandler.java:41) 
    at com.vaadin.server.VaadinService.handleRequest(VaadinService.java:1409) 
    at com.vaadin.server.VaadinServlet.service(VaadinServlet.java:364) 
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:729) 
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:292) 
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:207) 
    at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52) 
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:240) 
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:207) 
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:212) 
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:106) 
    at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:502) 
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:141) 
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:79) 
    at org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:616) 
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:88) 
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:528) 
    at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1099) 
    at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:672) 
    at org.apache.tomcat.util.net.AprEndpoint$SocketProcessor.doRun(AprEndpoint.java:2508) 
    at org.apache.tomcat.util.net.AprEndpoint$SocketProcessor.run(AprEndpoint.java:2497) 
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) 
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) 
    at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) 
    at java.lang.Thread.run(Thread.java:745) 

は、なぜそれが(いくつかの点で、必要な場合、またはその逆)の変換をLOCALDATEにStringを行うためのコンバータを登録していませんか?私は、同じ結果を持つTable.setConverterメソッドのパラメータとして匿名の内部クラスを使用しようとしました。私はここで間違って何をしていますか?

(リクエスト)UPDATE:ここ

表、容器とコンバータが使用されている完全なUIコードです。注:実際の目標がない「HelloVaadin」サンドボックスプロジェクトです。特にこの問題のような目的のために、Java 8のLocalDateをVaadinプロジェクトに統合しようとしています。

package be.kapture; 

import be.kapture.converters.LocalDateToDateConverter; 
import be.kapture.converters.LocalDateToStringConverter; 
import be.kapture.entities.Person; 
import be.kapture.util.CustomFieldGroupFieldFactory; 
import com.vaadin.annotations.*; 
import com.vaadin.data.fieldgroup.FieldGroup; 
import com.vaadin.data.util.BeanItem; 
import com.vaadin.data.util.BeanItemContainer; 
import com.vaadin.server.VaadinRequest; 
import com.vaadin.server.VaadinServlet; 
import com.vaadin.ui.*; 

import javax.servlet.annotation.WebServlet; 
import java.time.LocalDate; 
import java.util.Arrays; 

import static com.vaadin.data.Property.ValueChangeListener; 


@Theme("mytheme") 
@Widgetset("be.kapture.MyAppWidgetset") 
@PreserveOnRefresh 
@Title("Hello Vaadin!") 

public class MyUI extends UI implements Window.CloseListener { 

    private static final Person person1 = new Person(1L, "John", "DOE", LocalDate.of(70, 1, 1)); 
    private static final Person person2 = new Person(2L, "Jane", "doe", LocalDate.of(70, 1, 1)); 
    private static final Person person3 = new Person(3L, "jules", "winnf", LocalDate.of(48, 11, 21)); 
    private static final Person person4 = new Person(4L, "vincent", "Vega", LocalDate.of(54, 2, 17)); 

    private static final BeanItemContainer<Person> container = new BeanItemContainer<>(Person.class); 

    static { 
     container.addAll(Arrays.asList(person1, person2, person3, person4)); 
    } 

    private final VerticalLayout verticalLayout = new VerticalLayout(); 

    @Override 
    protected void init(VaadinRequest vaadinRequest) { 

     Person person = new Person(1L); 
     person.setFirstName("John"); 
     person.setLastName("Doe"); 
     person.setBirthdate(LocalDate.now()); 

     BeanItem<Person> beanItem = new BeanItem<>(person); 

     FieldGroup group = new FieldGroup(beanItem); 
     group.setFieldFactory(new CustomFieldGroupFieldFactory()); 

     Field<?> id = group.buildAndBind("id"); 
     Field<?> firstName = group.buildAndBind("firstName"); 
     Field<?> lastName = group.buildAndBind("lastName"); 

     Field<?> birthdate = group.buildAndBind("birthdate"); 

     Field<?> gender = group.buildAndBind("gender"); 

//  birthdate.setConverter(new LocalDateToDateConverter()); 
//  birthdate.setPropertyDataSource(item.getItemProperty("birthdate")); 
//  FormLayout layout = new FormLayout(id, firstName, lastName, 
//    birthdate); 
//  layout.setMargin(true); 
//  setContent(layout); 

     verticalLayout.setMargin(true); 
     verticalLayout.setSpacing(true); 

     verticalLayout.addComponents(id, firstName, lastName, birthdate, gender); 

     // Define a person which cannot exist 
     Person nullPerson = new Person(-1L); 
     nullPerson.setFirstName("Test"); 
     container.addItem(nullPerson); 
     final ListSelect select = new ListSelect("", container); 

     // Send events on directly when clicked 
     select.setImmediate(true); 

     // Handle the value of the person as null 
     select.setNullSelectionItemId(nullPerson); 
     select.setItemCaptionPropertyId("firstName"); 
     select.addValueChangeListener((ValueChangeListener) event -> System.out.println(select.getValue())); 

     verticalLayout.addComponent(select); 

     Table table = new Table(""); 
     table.setEditable(true); 
     table.setConverter(LocalDateToDateConverter.class); 
     table.setContainerDataSource(container); 

     verticalLayout.addComponent(table); 

     setContent(verticalLayout); 
    } 

    @Override 
    public void windowClose(Window.CloseEvent e) { 
     Notification.show("Window closed."); 
    } 

    @WebServlet(urlPatterns = "/*", name = "MyUIServlet", asyncSupported = true) 
    @VaadinServletConfiguration(ui = MyUI.class, productionMode = false) 
    public static class MyUIServlet extends VaadinServlet { 
    } 
} 
+0

コンテナを設定する前にコンバーターを設定しましたか? –

+0

@ A.Meierの場合、コンテナはテーブルのコンストラクタパラメータで設定されます。私は今、エラーを見ると思う。コンバータを最初に設定し、次にデータソースを設定する必要がありますか? –

+0

それは本当です。データソースはコンバータの後に設定する必要があります。 –

答えて

1

私は不思議であなたの問題を理解しました。メソッドsetConverter(Object, Converter)は、その列の値をユーザーに表示する方法(テキスト表現)を変更するだけです。 2番目の引数の型はConverter<java.lang.String,?>です。

この例では、テーブルで編集を有効にしました。これは、VaadinがあなたのLocalDateカラムのテーブルセルエディタをどのように提供するかを知ることを必要とします。デフォルトでは、テーブルにはLocalDateがありません。私はあなたが持っている2つのオプションを認識しています:

  1. StringLocalDateためConverterを返すconverter factoryを実装します。テーブルコンポーネントは、コンバータのフォーマットに従って日付を入力できるテキストフィールドを表示することができます。ユーザーが無効な文字列を入力したときに何が起きたのか試してみませんでした。
  2. table field factoryを実装し、テーブルコンポーネントに対してsetTableFieldFactoryを呼び出します。現場工場は、PopupDateFieldまたは類似のものを表示します。これにより、型保護され、組み込みの日付フィールドを使用できます。

IMOはユーザーエクスペリエンスが優れていますが、もちろん開発にもっと力を入れています。

+0

私はあなたの答えがハービッチ卿にあると信じています。 setEditable呼び出しをコメントアウトした後、UIはエラーなしで生成されます。 LocalDateフィールドは、単純なTextFieldのテーブルに表示されます。 TableFieldFactoryは最初の考えほど簡単ではないようです。私は、PopupDateFieldでそれを表示できるようにするために、LocalDateからDateまでのコンバータを必要とすると思いますか?私はVaadinがそれ以外のコンポーネントで認識されない日付型を表示する方法を見ていません。 –

+1

それは、LocalDate(モデル)からDate(プレゼンテーション)までのコンバータを実装し、そのコンバータをTableFieldFactoryで実行できるPopupDateFieldに設定する必要があります。 –

+1

私はコードを入力して、Steffenの入力に感謝します。 今後の読者のための参考資料:TableFieldFactoryとConverter を実装してください。あなたの工場でオーバーライドされたcreateFieldメソッドで:あなたのコンバータでフィールド/コンポーネントの呼び出しsetConverterメソッドで新しいPopupDateField(または何でも)を作成するかどうかをチェックする適切なデータソースでsetPropertyDatasourceを呼び出し、それを返します。他のすべての型については、作成をDefaultFieldFactory.get()。createFieldに委譲します。 –

関連する問題