I’ve decided to use Vaadin for an Monitoring Web App, and so far I’m very happy with that decission!
But I have one kinda bigger problem:
We have a Class MachineManager in a singelton architecture. This class starts a thread, which permanently updates the public BeanItemContainer this class ownes. This container is used as a Datasource for an Grid in an UI-thread.
Naturally, as we are using Java, the Container is copied, and changes in the Managers Container don’t arrive in the UI (only when refreshing). Do I have to accept my fate, and copy the container every few seconds to the UI or is there anything better in such situations?
Simplified:
public class MachineManager{
public BeanItemContainer<Machine> machineContainer = new BeanItemContainer<>(Machine.class);
// Singelton Architecture!
private static ManageMachines instance;
// Refresh machineContainer every 10 seconds
Thread autoRefresh = new Thread(new Runnable() {
public void run() {
while(true){
refreshAllMachines();
Thread.sleep(1000);
}
}
});
private ManageMachines () {
// start autorefreshing thread
autoRefresh.start();
}
.....
private void refreshAllMachines(){...
// Changes the content of machineContainer
}
}
[code]
public class ManageMachinesView extends HorizontalLayout implements View {
private Grid machineTable;
public ManageMachinesView(){
// Create Grid with all Machines
machineTable = new Grid(ManageMachines.getInstance().machineContainer);
machineTable.setEditorEnabled(false);
machineTable.setSelectionMode(SelectionMode.NONE);
// Parent Panel
Panel wrapperPanel = new Panel("Maschinen verwalten");
wrapperPanel.setContent(machineTable);
wrapperPanel.setSizeUndefined();
addComponent(wrapperPanel);
setComponentAlignment(wrapperPanel, Alignment.MIDDLE_CENTER);
setSizeFull();
}
@Override
public void enter(ViewChangeEvent event) {
if(VaadinSession.getCurrent().getAttribute("user") == null){
UI.getCurrent().getNavigator().navigateTo("");
}
}
}
[/code]I’ve already tried to edit the propertys by id (so the grid is notified), that didnt work.
I’ve also tried to get my own Container with Listeneners, but I failed with that.
Have you checked how to enable Vaadin Push and how to use UI.access() method in your threads? There is a chapter in Book of Vaadin covering the topic. I think this should solve most of your issues.
Vaadin Push is enabled, but it doesn’t seem to work. First I used the @push anotation, later i tried it with writing it in the web.xml.
The DataSource of the Grid is up to date.
I now implemented the Broadcaster like the example in the books. On every update there is a broadcast.
This is the receiveBroadcast method.
@Override
public void receiveBroadcast(String message) {
indexUI.getCurrent().access(new Runnable() {
@Override
public void run() {
machineTable = new Grid(ManageMachines.getInstance().machineContainer);
}
});
}
This method is executed, an system.out… works. So there seems to be an issue with “Push”. It doesn’t even work to add an label or something.
This is a kind of strange, because the automatic push works just fine in an other view.
Tho only other thing I have is this Warning, when first visiting the UI:
Jan 12, 2016 1:11:07 PM com.vaadin.server.communication.PushAtmosphereHandler onRequest
WARNUNG: AtmosphereHandler.onRequest called before PushHandler has been set. This should really not happen
But I don’t know what this should mean. Google didn’t help me either.
How do you call receiveBroadcast? I would bet that “indexUI.getCurrent()” returns the wrong UI instance in at least some cases (the UI instance of the caller thread). It’s much safer to store the UI instance in the listener and use that