Question

I'm looking for a way to use a jpa relationship @OneToMany/@OneToOne/@ManyToOne/@ManyToMany with a ComboBox.

@Entity
public class State {

    @Id
    @GeneratedValue
    private Integer id;

    @NotNull @NotEmpty @Size(min=5, max=50)
    private String state;

    @OneToOne
    private Governor governor;

}

@Entity
public class Governor {

    @Id
    @GeneratedValue
    private Integer id;

    @NotNull @NotEmpty @Size(min=5, max=50)
    private String governor;

}

//app
public class StateView extends VerticalLayout {
    //jpacontainer
    private final CustomJPAContainer<State> datasource = new CustomJPAContainer<State>(State.class);

    //attributes
    private String state;
    private ComboBox governor;
    private final BeanFieldGroup<State> binder = new BeanFieldGroup<State>(State.class);
    private State bean = new State();


    public StateView(){
         Field<?> field = null;

         //state
         field = binder.buildAndBind("State", "state");
         state = binder.getField("state");
         vLayout.addComponent(state);

         //combo governor
         here, how to create combobox to governor relationship ?

    }
}

How I do to create a combobox with this relationship using JPAContainer ?

Edited*

/** datasources */
private final CustomJPAContainer<State> datasource = new CustomJPAContainer<State>(Curriculum.class);
private final CustomJPAContainer<Governor> dsGovernor = new CustomJPAContainer<Governor>(Governor.class);

//governor combobox
field = binder.buildAndBind("Governor", "governor", ComboBox.class);        
governor = (ComboBox)binder.getField("governor");
governor.setContainerDataSource(dsGovernor);        
governor.setItemCaptionPropertyId("governor");      
governor.setImmediate(true);
governor.select(0);
vLayout.addComponent(governor);

//button click
binder.commit()

When I try commit, return this error.

com.vaadin.data.fieldgroup.FieldGroup$CommitException: Commit failed
    at com.vaadin.data.fieldgroup.FieldGroup.commit(FieldGroup.java:463)
    at br.ind.ibg.views.StateView.buttonClick(StateView.java:142)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:606)
    at com.vaadin.event.ListenerMethod.receiveEvent(ListenerMethod.java:508)
    at com.vaadin.event.EventRouter.fireEvent(EventRouter.java:198)
    at com.vaadin.event.EventRouter.fireEvent(EventRouter.java:161)
    at com.vaadin.server.AbstractClientConnector.fireEvent(AbstractClientConnector.java:969)
    at com.vaadin.ui.Button.fireClick(Button.java:368)
    at com.vaadin.ui.Button$1.click(Button.java:57)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:606)
    at com.vaadin.server.ServerRpcManager.applyInvocation(ServerRpcManager.java:168)
    at com.vaadin.server.ServerRpcManager.applyInvocation(ServerRpcManager.java:118)
    at com.vaadin.server.communication.ServerRpcHandler.handleBurst(ServerRpcHandler.java:207)
    at com.vaadin.server.communication.ServerRpcHandler.handleRpc(ServerRpcHandler.java:111)
    at com.vaadin.server.communication.UidlRequestHandler.synchronizedHandleRequest(UidlRequestHandler.java:91)
    at com.vaadin.server.SynchronizedRequestHandler.handleRequest(SynchronizedRequestHandler.java:37)
    at com.vaadin.server.VaadinService.handleRequest(VaadinService.java:1382)
    at com.vaadin.server.VaadinServlet.service(VaadinServlet.java:238)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:727)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:303)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
    at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:220)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:122)
    at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:501)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:170)
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:98)
    at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:950)
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:116)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:408)
    at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1040)
    at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:607)
    at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:313)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
    at java.lang.Thread.run(Thread.java:724)
Caused by: com.vaadin.data.Buffered$SourceException
    at com.vaadin.ui.AbstractField.commit(AbstractField.java:251)
    at com.vaadin.data.fieldgroup.FieldGroup.commit(FieldGroup.java:443)
    ... 43 more
Caused by: com.vaadin.data.util.converter.Converter$ConversionException: Could not convert value to Governor
    at com.vaadin.ui.AbstractField.convertToModel(AbstractField.java:748)
    at com.vaadin.ui.AbstractField.convertToModel(AbstractField.java:725)
    at com.vaadin.ui.AbstractField.getConvertedValue(AbstractField.java:811)
    at com.vaadin.ui.AbstractField.commit(AbstractField.java:247)
    ... 44 more
Caused by: com.vaadin.data.util.converter.Converter$ConversionException: Unable to convert value of type java.lang.Integer to model type class br.ind.ibg.beans.Governor. No converter is set and the types are not compatible.
    at com.vaadin.data.util.converter.ConverterUtil.convertToModel(ConverterUtil.java:181)
    at com.vaadin.ui.AbstractField.convertToModel(AbstractField.java:745)
    ... 47 more
Was it helpful?

Solution

A straight forward solution:

BeanItemContainer<State> container = new BeanItemContainer<State>(State.class);

final BeanFieldGroup<State> binder = new BeanFieldGroup<State>(State.class);
binder.setFieldFactory(new DefaultFieldGroupFieldFactory() {

    @SuppressWarnings("unchecked")
    @Override
    public <T extends Field> T createField(Class<?> type, Class<T> fieldType) {

        if (type.isAssignableFrom(Governor.class) && fieldType.isAssignableFrom(ComboBox.class)) {
            return (T) new ComboBox(); // we create a ComboBox for the Governor property
        }

        return super.createField(type, fieldType);
    }

});

final State bean = new State();

Field<?> field = null;
binder.setItemDataSource(bean);

binder.buildAndBind("State", "state");
field = binder.buildAndBind("Governor", "governor", ComboBox.class);

ComboBox cmbx = (ComboBox) field;

// We define a container data source for your Governors.
// I've taken the BeanItemContainer
cmbx.setContainerDataSource(new BeanItemContainer<Governor>(Governor.class));

// If you want to use a JPAContainer you need to translate entities to identifiers and visa versa
// cmbx.setContainerDataSource(dsGovernor);
// cmbx.setConverter(new SingleSelectConverter<Governor>(cmbx));
cmbx.setItemCaptionPropertyId("governor");

// we create two dummy Governors
Governor governorA = new Governor();
governorA.setGovernor("A");
Governor governorB = new Governor();
governorB.setGovernor("B");

// ... and add them to the container
cmbx.getContainerDataSource().addItem(governorA);
cmbx.getContainerDataSource().addItem(governorB);

// when the binder is committed the value of the ComboBox ( getValue() )is mapped to our state bean.

OTHER TIPS

This question is related to another question on Stackoverflow: Vaadin 7.0.1 Combobox with JPAContainer and FieldGroup.

I wrote a blog post about this topic which explains how FieldGroups work internally and how you can make them work for this particular use case: Select Nested JavaBeans With a Vaadin FieldGroup. This post will also explain why a ConversionException is thrown in your example.

Of course you could switch to using a BeanItemContainer, but by using a simple Converter implementation you can use any Container implementation as data source for your ComboBox. See the blog post for details.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top