ComboBox/JPAContainer

When I call ComboBox.setItemDataSource() and pass an item from a JPAContainer, the component does not display the selected value. I was able to make this work with a BeanItemContainer, but I don’t remember doing anything special. equals() has been implemented for the class and appears to be working correctly. Am I missing something here?

I don’t have a solution yet, but ComboBox.value is receiving the entity as the value when it should be receiving the entitiy’s id.

Hello,

Have you checked out the JPAContainer demo application? It uses a ComboBox.

-Petter-

I have not, but I certainly will.

I did give the demo app a whirl and here’s my issue…if my entity has a many-to-one relationship to another entity (ie. TableItem to ItemStatus) and the TableItem entity is displayed in a table and then edited in a form with the ComboBox which uses JPAItemStatusContainer as its datasource, you listen for the click event on the table and then call Form.setItemDatasource() which in turn calls Field.setPropertyDataSource(). Over in Select.paintContent(), the code iterates over the property Id’s (String’s) and then compares them against the value in AbstractSelect.isSelected() which is the entity itself in this case when it should be comparing against the entity’s Id. My explanation of the issue may not be 100% clear, but I’m just looking over the Vaadin code since the actual code experiencing the issue is at work. Still haven’t figured out the best solution, but I wanted to share my thoughts.

Woohoo! The solution was surprisingly simple. I created an anonymous subclass of CombBox and overrided getValue()

Here’s my solution (you will need to adapt slightly). Yes, some of the code may look similar to what’s in JPAContainer, but let’s not depend on that implementation.


private class EntityComboBox extends ComboBox {
    
    private Class<? extends AbstractEntity<?>> entityClass;
    
    public EntityComboBox(String caption, Container dataSource, Class<? extends AbstractEntity<?>> entityClass) {
        super(caption, dataSource);
        this.entityClass = entityClass;
        setImmediate(true);
        setItemCaptionPropertyId("value");
        setNullSelectionAllowed(false);
    }
    
    @Override
    public Class getType() {
        return entityClass;
    }
    
    @Override
    protected void setInternalValue(Object newValue) {
        if (newValue != null 
				&& !entityClass.isAssignableFrom(newValue.getClass())) {
            try {
                newValue = entityClass
                            .getConstructor(new Class[] {String.class})
                                .newInstance(new Object[] {newValue});
            } catch (Exception e) {
                throw new ConversionException(e);
            }
        }
        
        super.setInternalValue(newValue);
    }
    
    @Override
    public boolean isSelected(Object itemId) {
        return itemId != null && itemId.equals(((AbstractEntity<?>) getValue()).getId()); 
    }
    
}

Hey guys, I getting the some problem.

I’m using:

  • hibernate 4
  • jpacontainer 2.1
  • vaadin 6.8.2

I alredy tried the solution above, but without success!

I’m getting an exception:


com.vaadin.data.Buffered$SourceException
	at com.vaadin.ui.AbstractField.setValue(AbstractField.java:543)
	at com.vaadin.ui.AbstractSelect.setValue(AbstractSelect.java:674)
	at com.vaadin.ui.Select.changeVariables(Select.java:657)
	at com.vaadin.terminal.gwt.server.AbstractCommunicationManager.changeVariables(AbstractCommunicationManager.java:1460)
	at com.vaadin.terminal.gwt.server.AbstractCommunicationManager.handleVariableBurst(AbstractCommunicationManager.java:1404)
	at com.vaadin.terminal.gwt.server.AbstractCommunicationManager.handleVariables(AbstractCommunicationManager.java:1329)
	at com.vaadin.terminal.gwt.server.AbstractCommunicationManager.doHandleUidlRequest(AbstractCommunicationManager.java:761)
	at com.vaadin.terminal.gwt.server.CommunicationManager.handleUidlRequest(CommunicationManager.java:318)
	at com.vaadin.terminal.gwt.server.AbstractApplicationServlet.service(AbstractApplicationServlet.java:501)
	at javax.servlet.http.HttpServlet.service(HttpServlet.java:722)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:305)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
	at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:225)
	at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:169)
	at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:472)
	at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:168)
	at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:98)
	at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:927)
	at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118)
	at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:407)
	at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:999)
	at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:565)
	at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:309)
	at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
	at java.lang.Thread.run(Thread.java:662)
Caused by: com.vaadin.data.Property$ConversionException: java.lang.NoSuchMethodException: br.com.jjw.suporteweb.model.Sistema.<init>(java.lang.String)
	at com.vaadin.addon.jpacontainer.JPAContainerItem$ItemProperty.setValue(JPAContainerItem.java:277)
	at com.vaadin.ui.AbstractField.setValue(AbstractField.java:535)
	... 25 more
Caused by: java.lang.NoSuchMethodException: br.com.jjw.suporteweb.model.Sistema.<init>(java.lang.String)
	at java.lang.Class.getConstructor0(Class.java:2706)
	at java.lang.Class.getConstructor(Class.java:1657)
	at com.vaadin.addon.jpacontainer.JPAContainerItem$ItemProperty.setValue(JPAContainerItem.java:271)
	... 26 more

Hi,

Since JPAContainer 2 there has been a helper (Item wrapper) called SingleSelectTranslator. Without seeing your code, my best guess is that it is exactly what you are looking for.

cheers,
matti

This is my code (simplified):


  // the model
  class Questao {
     Sistema sistema;
  } 

  class Sistema {
    int id;
    String nome;
  }

  // my Table datasource
  JPAContainer<Questao> container = JPAContainerFactory.make(Questao.class, PersistenceUnit.NAME);
  MyTableInstance.setContainerDataSource(container);

  // on table selection change I set the MyForm.setItemDataSource(jpaContainerItem);

  // my form
  Form myForm = new Form();
  myFom.setFormFieldFactory(new MyFieldFactoryForComboBox()  
  {
       public Field createField(.......) { 
           if (propertyId.equals("sistema")) {
          ComboBox cbxSistema = new ComboBox();
         JPAContainer<Sistema> container = JPAContainerFactory.make(Sistema.class, PersistenceUnit.NAME); 
          cbxSistema.setContainerDataSource(container);
          return cbxSistema;
          }
          ......
       }
  }
  );

The problem occurrs when:

  • After select a record, the combobox doesn’t shows the currently SISTEMA
  • On select a SISTEMA in the combobox the exception above occurrs

Hi,

Exactly. Property value Sistema and the identifiers in container (from which ComboBox pics one) are Integers(=identifiers). You should have this in your field factory:


cbxSistema .setItemDataSource(new SingleSelectTranslator());

Or you could simply try your luck with com.vaadin.addon.jpacontainer.fieldfactory.FieldFactory in your Table.

cheers,
matti

I solved the problem using CustomField addon and based on JPAContainer Address Book

:smiley:

Thanks!

That’s one way to do it - glad to hear you solved it. The demo is older than the SingleSelectTranslator so that is why it is not using it.

cheers,
matti

I have a problem. I think it’s a bit like that. I have a combobox that is a containerDataSource, which is configured to list the data according to the selected firm. However, no time to send the data, FieldGroup can not, because I need to record the ID of the selected item, but the name is being selected. This ID must be recorded as a foreign key.

Someone help?