Change item in BeanItemContainer

Hi together,

I stuck in problems changing items in my BeanItemContainer. The container is the datasource of my grid and the container is filled with a list. Now I want to change a row in my grid. To do this, I’m trying to change an item in the list or in the container but I dont know how. Whenever I change an item in the list, I get java.lang.NullPointerException.

Some code:

List<Kontrakt> kontrakte = Arrays.asList(
          new Kontrakt[]{
              //added some stuff
          });

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

container.addAll(kontrakte);
grid.setContainerDataSource(container);

container.getItem(kontrakte.get(0)).getBean().setName("example");

I know that I could remove the item from the container, change it and add it again. But then the “new” row is always at the bottom of the list and I don’t want to change the order by changing an item.

Thanks for your great help

Can you post the stack trace?
Have you implemented equals and hashcode on Kontrakt class?

Yes I’ve implemented hascode and equals on Kontrakt class.
Is my way to change the list item even the right way to edit the row?

Jun 06, 2016 12:37:01 PM com.vaadin.server.DefaultErrorHandler doDefault
SCHWERWIEGEND:
java.util.concurrent.ExecutionException: java.lang.NullPointerException
at java.util.concurrent.FutureTask.report(Unknown Source)
at java.util.concurrent.FutureTask.get(Unknown Source)
at com.vaadin.server.VaadinSession$FutureAccess.get(VaadinSession.java:124)
at com.vaadin.server.VaadinService.runPendingAccessTasks(VaadinService.java:1838)
at com.vaadin.server.VaadinSession.unlock(VaadinSession.java:990)
at com.vaadin.server.VaadinService.ensureAccessQueuePurged(VaadinService.java:1799)
at com.vaadin.server.VaadinService.accessSession(VaadinService.java:1765)
at com.vaadin.server.VaadinSession.access(VaadinSession.java:1380)
at com.vaadin.ui.UI.access(UI.java:1444)
at frontend.thesis.webapp.Fenster$4.run(Fenster.java:173)
at java.util.TimerThread.mainLoop(Unknown Source)
at java.util.TimerThread.run(Unknown Source)
Caused by: java.lang.NullPointerException
at frontend.thesis.webapp.Fenster$4.lambda$0(Fenster.java:173)
at com.vaadin.ui.UI.accessSynchronously(UI.java:1381)
at com.vaadin.ui.UI$3.run(UI.java:1447)
at java.util.concurrent.Executors$RunnableAdapter.call(Unknown Source)
at java.util.concurrent.FutureTask.run(Unknown Source)
at com.vaadin.server.VaadinService.runPendingAccessTasks(VaadinService.java:1835)
… 8 more

It could be better update the item using the container property directly, so value change events are fired

container.getContainerProperty(kontrakte.get(0), "name").setValue("example"); Can you post the whole Fenster class?

I tried the container property you have provided with this error:

Jun 06, 2016 1:11:05 PM com.vaadin.server.DefaultErrorHandler doDefault
SCHWERWIEGEND:
java.lang.NullPointerException
at com.vaadin.ui.Grid$RowDataGenerator.writeData(Grid.java:2198)
at com.vaadin.ui.Grid$RowDataGenerator.generateData(Grid.java:2158)
at com.vaadin.server.communication.data.RpcDataProviderExtension.getRowData(RpcDataProviderExtension.java:395)
at com.vaadin.server.communication.data.RpcDataProviderExtension.pushRowData(RpcDataProviderExtension.java:383)
at com.vaadin.server.communication.data.RpcDataProviderExtension.beforeClientResponse(RpcDataProviderExtension.java:334)
at com.vaadin.server.communication.UidlWriter.write(UidlWriter.java:112)
at com.vaadin.server.communication.AtmospherePushConnection.push(AtmospherePushConnection.java:168)
at com.vaadin.server.communication.PushHandler$2.run(PushHandler.java:150)
at com.vaadin.server.communication.PushHandler.callWithUi(PushHandler.java:243)
at com.vaadin.server.communication.PushHandler.onMessage(PushHandler.java:503)
at com.vaadin.server.communication.PushAtmosphereHandler.onMessage(PushAtmosphereHandler.java:88)
at com.vaadin.server.communication.PushAtmosphereHandler.onRequest(PushAtmosphereHandler.java:78)
at org.atmosphere.cpr.AsynchronousProcessor.action(AsynchronousProcessor.java:199)
at org.atmosphere.cpr.AsynchronousProcessor.suspended(AsynchronousProcessor.java:107)
at org.atmosphere.container.Servlet30CometSupport.service(Servlet30CometSupport.java:66)
at org.atmosphere.cpr.AtmosphereFramework.doCometSupport(AtmosphereFramework.java:2075)
at org.atmosphere.websocket.DefaultWebSocketProcessor.dispatch(DefaultWebSocketProcessor.java:571)
at org.atmosphere.websocket.DefaultWebSocketProcessor$3.run(DefaultWebSocketProcessor.java:333)
at org.atmosphere.util.VoidExecutorService.execute(VoidExecutorService.java:101)
at org.atmosphere.websocket.DefaultWebSocketProcessor.dispatch(DefaultWebSocketProcessor.java:328)
at org.atmosphere.websocket.DefaultWebSocketProcessor.invokeWebSocketProtocol(DefaultWebSocketProcessor.java:425)
at org.atmosphere.container.JSR356Endpoint$1.onMessage(JSR356Endpoint.java:213)
at org.atmosphere.container.JSR356Endpoint$1.onMessage(JSR356Endpoint.java:210)
at org.apache.tomcat.websocket.WsFrameBase.sendMessageText(WsFrameBase.java:399)
at org.apache.tomcat.websocket.WsFrameBase.processDataText(WsFrameBase.java:500)
at org.apache.tomcat.websocket.WsFrameBase.processData(WsFrameBase.java:295)
at org.apache.tomcat.websocket.WsFrameBase.processInputBuffer(WsFrameBase.java:131)
at org.apache.tomcat.websocket.server.WsFrameServer.onDataAvailable(WsFrameServer.java:71)
at org.apache.tomcat.websocket.server.WsHttpUpgradeHandler$WsReadListener.onDataAvailable(WsHttpUpgradeHandler.java:185)
at org.apache.coyote.http11.upgrade.AbstractServletInputStream.onDataAvailable(AbstractServletInputStream.java:198)
at org.apache.coyote.http11.upgrade.AbstractProcessor.upgradeDispatch(AbstractProcessor.java:96)
at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:647)
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1520)
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.run(NioEndpoint.java:1476)
at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
at java.lang.Thread.run(Unknown Source)

My Fenster class:[code]
public class Fenster extends Window {
Grid grid;
public Fenster() {
super(“Orderbuch”); // Set window caption
center();
setWidth(“600px”);

    VerticalLayout content = new VerticalLayout();
    grid = new Grid();
    grid.setColumnReorderingAllowed(true);
    grid.setSizeFull();
    grid.setEditorEnabled(true);
    
    List<Kontrakt> kontrakte = Arrays.asList(
            new Kontrakt[]{
                    new Kontrakt("item",1),
                    new Kontrakt("item2",2)
            });
    
    BeanItemContainer<Kontrakt> container =
            new BeanItemContainer<Kontrakt2>(Kontrakt.class);
    container.addAll(kontrakte);
    
    grid.setContainerDataSource(container);
    
    grid.setColumnOrder("name","id");
    grid.removeColumn("id");
    
    container.getContainerProperty(kontrakte.get(0), "name").setValue("example");
    
    content.addComponent(grid);
    content.setMargin(true);
    setContent(content);
}

}
[/code]

It works for me; I’m able to reproduce your last error only if I add mutable
name
property in the equals implementation of Kontrakt

I’m not sure what you mean. I generated the equals and the part with
name
looks like this:

if (name == null) {
            if (other.name != null)
                return false;
        } else if (!name.equals(other.name))
            return false;

Sorry, in my previous answer I wrote “equals implementation” but I meant “hashcode implementation”.

If your hashcode implementation is based on the mutable field
name
then the BeanItemContainer could not lookup the bean from his internal
itemIdToItem
HashMap after modification as stated in
javadocs

If you cannot modify the hashcode implementation you should end up wiht a remove, modify and insert operation

//container.getContainerProperty(kontrakte.get(0), "name").setValue("example");
Kontrakt kontrakt = kontrakte.get(0);
int idx = container.indexOfId(kontrakt);
container.removeItem(kontrakt); kontrakt.setName("example");
container.addItemAt(idx, kontrakt); 

HTH

I deleted my hashcode in the kontrakt class. Now I can change the name property with:

container.getContainerProperty(kontrakte.get(0), "name").setValue("example"); I added another column
bidqty
to my grid and tried to change it the same way:

container.getContainerProperty(kontrakte.get(0), "bidqty").setValue(12);

​Unfortunately I get the error:

Exception in thread “Timer-6” com.vaadin.data.Property$ReadOnlyException
at com.vaadin.data.util.MethodProperty.setValue(MethodProperty.java:644)
at frontend.thesis.webapp.Fenster$1$1.run(Fenster.java:172)
at java.util.TimerThread.mainLoop(Unknown Source)
at java.util.TimerThread.run(Unknown Source)

And:

grid.setReadOnly(false);
container.getContainerProperty(kontrakte.get(0), "bidqty").setReadOnly(false);

doens’t help to solve the error.

The first thing I can suppose is that your Kontract class does not have a public setter method

public void setBidqty(int qty) 

Was my first thought as well, but my class has

    public void setBidqty(int bidqty) {
        this.bidqty = bidqty;
    }

Ok I solved it. It’s working now.
The setter wasn’t the problem but the getter. I returned a String and not a int because it was easier for me to display the value of the int in the table. This was my getter:

public String getBidqty() { return String.valueOf(bidqty); } I changed it to:

public int getBidqty() { return bidqty; } and now I can edit the bidqty property as well.

Thank you for your help!!

I had a similar problem, but with a ComboBox. In my case, I had to change

public void setCertificateOfCompliance( Boolean certificateOfCompliance ){ if( certificateOfCompliance instanceof Boolean ) setCertificateOfCompliance( certificateOfCompliance.toString() ); else setCertificateOfCompliance( "false" ); } in my bean to public void setCertificateOfCompliance( boolean certificateOfCompliance ){ setCertificateOfCompliance( "" + certificateOfCompliance ); } So thanks for your help - it pointed me in the right direction. My problem was almost certainly the fact that the “setCertificateOfCompliance( String value )” was getting confused with “setCertificateofCompliance( Boolean value )” by the “BeanFieldGroup.bindFieldsUnbuffered” method call.