@Push causing errors and not functioning properly

I’m attempting to use a background thread to keep a status panel up-to-date on my web application.
It needs to poll the database every second and update the panel.

I figured that the best way to do this would be to spawn a new thread and have it update the panel for me, which has not gone as smoothly as I would’ve liked. I have included the errors and code I’ve written below.

I’m using Vaadin 12.0.4. Any suggestions or ideas on how I can accomplish my goal are appreciated.

Here’s the related code:

  1. MainLayout.java
// @PWA(name = "DICES VoIP Web SAT", shortName = "WebSAT")
@HtmlImport("frontend://styles/shared-styles.html")
@Viewport("width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes")
@StyleSheet("frontend://styles/style.css")
@Push
public class MainLayout extends Div implements RouterLayout, PageConfigurator, BeforeEnterObserver {
... 
}
  1. StatusPanel.java
public class StatusPanel extends HorizontalLayout {
    Thread thread;
	...
    int i = 0;

    @Override
    protected void onAttach(AttachEvent attachEvent) {
        // Start the data feed thread
        thread = new FeederThread(attachEvent.getUI(), this);
        thread.start();
    }

    @Override
    protected void onDetach(DetachEvent detachEvent) {
        // Cleanup
        thread.interrupt();
        thread = null;
    }

    private static class FeederThread extends Thread {
        private final UI ui;
        private final StatusPanel view;

        private int count = 0;

        public FeederThread(UI ui, StatusPanel view) {
            this.ui = ui;
            this.view = view;
        }

        @Override
        public void run() {
            try {
                while(!Thread.currentThread().isInterrupted()) {
                    ui.access(() -> {
                        Result<SystemManagerDBO> systemManagerResult = Globals.dbi2.tables.systemManager.get("ip_address", ip_address);
                        if (systemManagerResult.getCount() >= 1) {
                            try {
                                SystemManagerDBO systemManager = systemManagerResult.getDBO();
                                RoleDBO role = systemManager.getHostDBO().getRoleDBO();
                                String serverText = systemManager.getHostDBO().getName() + view.i++;
                                view.serverLabel.setText(serverText);
                                System.out.println("Loading status bar: " + serverText + " " + view.serverLabel.getText());
                                setStatus(true, view.serverStatus);

                                if (role != null) {
                                    view.roleLabel.setText(role.getName());
                                    setStatus(true, view.roleStatus);
                                } else {
                                    view.roleLabel.setText("N/A");
                                    setStatus(false, view.roleStatus);
                                }

                            } catch (DBONotFoundException e) {
                                view.serverLabel.setText("Connected");
                                view.roleLabel.setText("N/A");
                                setStatus(true, view.serverStatus);
                                setStatus(false, view.roleStatus);
                            }
                        } else {
                            view.serverLabel.setText("Disconnected");
                            view.roleLabel.setText("N/A");

                            setStatus(false, view.serverStatus);
                            setStatus(false, view.roleStatus);
                        }

                    });
                    Thread.sleep(1000);
                }
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
                return;
            }
        }
    }	

Output from my System.out.println() call that proves that this is getting ran every second as it should be, and that it’s updating the objects.

Loading status bar: WebSAT0 WebSAT0
Loading status bar: WebSAT1 WebSAT1
Loading status bar: WebSAT2 WebSAT2
Loading status bar: WebSAT3 WebSAT3

However, it’s not updating the HTML element, even though I have enabled @Push.

I have also tried manual push, same result.

I get the following errors when it’s running:

[Atmosphere-Shared-0]
 ERROR com.vaadin.flow.server.communication.PushAtmosphereHandler - Exception in push connection
org.eclipse.jetty.io.EofException
	at org.eclipse.jetty.server.HttpConnection$SendCallback.reset(HttpConnection.java:714)
	at org.eclipse.jetty.server.HttpConnection$SendCallback.access$300(HttpConnection.java:678)
	at org.eclipse.jetty.server.HttpConnection.send(HttpConnection.java:536)
	at org.eclipse.jetty.server.HttpChannel.sendResponse(HttpChannel.java:790)
	at org.eclipse.jetty.server.HttpChannel.write(HttpChannel.java:846)
	at org.eclipse.jetty.server.HttpOutput.write(HttpOutput.java:240)
	at org.eclipse.jetty.server.HttpOutput.write(HttpOutput.java:216)
	at org.eclipse.jetty.server.HttpOutput.flush(HttpOutput.java:398)
	at org.atmosphere.handler.AbstractReflectorAtmosphereHandler.onStateChange(AbstractReflectorAtmosphereHandler.java:156)
	at com.vaadin.flow.server.communication.PushAtmosphereHandler.onStateChange(PushAtmosphereHandler.java:52)
	at org.atmosphere.cpr.DefaultBroadcaster.invokeOnStateChange(DefaultBroadcaster.java:1037)
	at org.atmosphere.cpr.DefaultBroadcaster.prepareInvokeOnStateChange(DefaultBroadcaster.java:1057)
	at org.atmosphere.cpr.DefaultBroadcaster.executeAsyncWrite(DefaultBroadcaster.java:871)
	at org.atmosphere.cpr.DefaultBroadcaster$2.run(DefaultBroadcaster.java:474)
	at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
	at java.util.concurrent.FutureTask.run(FutureTask.java:266)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
	at java.lang.Thread.run(Thread.java:748)
[qtp353296011-18]
 ERROR com.vaadin.flow.server.DefaultErrorHandler - 
java.lang.UnsupportedOperationException: FIXME: Implement resync
	at com.vaadin.flow.server.communication.ServerRpcHandler.handleRpc(ServerRpcHandler.java:315)
	at com.vaadin.flow.server.communication.UidlRequestHandler.synchronizedHandleRequest(UidlRequestHandler.java:89)
	at com.vaadin.flow.server.SynchronizedRequestHandler.handleRequest(SynchronizedRequestHandler.java:40)
	at com.vaadin.flow.server.VaadinService.handleRequest(VaadinService.java:1533)
	at com.vaadin.flow.server.VaadinServlet.service(VaadinServlet.java:227)
	at javax.servlet.http.HttpServlet.service(HttpServlet.java:790)
	at org.eclipse.jetty.servlet.ServletHolder.handle(ServletHolder.java:865)
	at org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:535)
	at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:146)
	at org.eclipse.jetty.security.SecurityHandler.handle(SecurityHandler.java:548)
	at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:132)
	at org.eclipse.jetty.server.handler.ScopedHandler.nextHandle(ScopedHandler.java:257)
	at org.eclipse.jetty.server.session.SessionHandler.doHandle(SessionHandler.java:1595)
	at org.eclipse.jetty.server.handler.ScopedHandler.nextHandle(ScopedHandler.java:255)
	at org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:1317)
	at org.eclipse.jetty.server.handler.ScopedHandler.nextScope(ScopedHandler.java:203)
	at org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:473)
	at org.eclipse.jetty.server.session.SessionHandler.doScope(SessionHandler.java:1564)
	at org.eclipse.jetty.server.handler.ScopedHandler.nextScope(ScopedHandler.java:201)
	at org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:1219)
	at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:144)
	at org.eclipse.jetty.server.handler.ContextHandlerCollection.handle(ContextHandlerCollection.java:219)
	at org.eclipse.jetty.server.handler.HandlerCollection.handle(HandlerCollection.java:126)
	at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:132)
	at org.eclipse.jetty.server.Server.handle(Server.java:531)
	at org.eclipse.jetty.server.HttpChannel.handle(HttpChannel.java:352)
	at org.eclipse.jetty.server.HttpConnection.onFillable(HttpConnection.java:260)
	at org.eclipse.jetty.io.AbstractConnection$ReadCallback.succeeded(AbstractConnection.java:281)
	at org.eclipse.jetty.io.FillInterest.fillable(FillInterest.java:102)
	at org.eclipse.jetty.io.ChannelEndPoint$2.run(ChannelEndPoint.java:118)
	at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.runTask(EatWhatYouKill.java:333)
	at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.doProduce(EatWhatYouKill.java:310)
	at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.tryProduce(EatWhatYouKill.java:168)
	at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.run(EatWhatYouKill.java:126)
	at org.eclipse.jetty.util.thread.ReservedThreadExecutor$ReservedThread.run(ReservedThreadExecutor.java:366)
	at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:762)
	at org.eclipse.jetty.util.thread.QueuedThreadPool$2.run(QueuedThreadPool.java:680)
	at java.lang.Thread.run(Thread.java:748)

And if the server is left running long enough I get the following errors aproximately every millisecond

[qtp353296011-26]
 WARN com.vaadin.flow.server.communication.PushHandler - Invalid identifier in new connection received from 0:0:0:0:0:0:0:1
[qtp353296011-43]
 WARN com.vaadin.flow.server.communication.PushHandler - Invalid identifier in new connection received from 0:0:0:0:0:0:0:1
[qtp353296011-26]
 WARN com.vaadin.flow.server.communication.PushHandler - Invalid identifier in new connection received from 0:0:0:0:0:0:0:1
[qtp353296011-43]
 WARN com.vaadin.flow.server.communication.PushHandler - Invalid identifier in new connection received from 0:0:0:0:0:0:0:1
[qtp353296011-26]
 WARN com.vaadin.flow.server.communication.PushHandler - Invalid identifier in new connection received from 0:0:0:0:0:0:0:1
[qtp353296011-43]
 WARN com.vaadin.flow.server.communication.PushHandler - Invalid identifier in new connection received from 0:0:0:0:0:0:0:1
[qtp353296011-26]
 WARN com.vaadin.flow.server.communication.PushHandler - Invalid identifier in new connection received from 0:0:0:0:0:0:0:1
[qtp353296011-43]
 WARN com.vaadin.flow.server.communication.PushHandler - Invalid identifier in new connection received from 0:0:0:0:0:0:0:1
[qtp353296011-26]
 WARN com.vaadin.flow.server.communication.PushHandler - Invalid identifier in new connection received from 0:0:0:0:0:0:0:1

There is one thing that you could do in order to make your code behave more nicely. I see that you have calls to business logic also inside ui.access(), ei refer to this code

			Result<SystemManagerDBO> systemManagerResult = Globals.dbi2.tables.systemManager.get("ip_address", ip_address);
			if (systemManagerResult.getCount() >= 1) {
				try {
					SystemManagerDBO systemManager = systemManagerResult.getDBO();
					RoleDBO role = systemManager.getHostDBO().getRoleDBO();
					String serverText = systemManager.getHostDBO().getName() + view.i++;

I would recommend to refactor that out side ui.access(). It is adviced that to do only the updates of the UI in access, in order to keep the locking time as short as possible. This is especially important if you plan do quite frequent updates like here.

Look at that, it works now!

I feel like this information should be in big bold letters on this page: https://vaadin.com/docs/v12/flow/advanced/tutorial-push-access.html

I was using the example there, and while it does call ui.access() multiple times in the same method, it never mentions why it does that.

Thanks a bunch! Now I can have these features in by my deadline!

I have changed it to use this in all places, rolled the time back to 10 seconds, and @Push is still causing issues; just not as severe this time. I get:

[qtp136011184-21]
 WARN com.vaadin.flow.server.communication.PushHandler - Invalid identifier in new connection received from 0:0:0:0:0:0:0:1

and then my session hangs and i need to restart my server.

It also has caused page loading to sometimes hang and not load the page.

Is there a better way to do what I want to do than @Push()?

This just in: My situation improved dramatically after turning off the jetty scanner and switching to manual push

My situation improved dramatically after turning off the jetty scanner and switching to manual push

We would be interested to know which version of Jetty you used?

    <build>
        <plugins>
            <!-- Jetty plugin for easy testing without a server -->
            <plugin>
                <groupId>org.eclipse.jetty</groupId>
                <artifactId>jetty-maven-plugin</artifactId>
                <version>9.4.11.v20180605</version>
                <configuration>
                    <scanIntervalSeconds>0</scanIntervalSeconds>
                </configuration>
            </plugin>
        </plugins>
    </build>

I believe that the issue with jetty was it conflicting with IntelliJ, and every time I did so much as move the cursor, the watcher was reading the .idea folder and restarting, causing a disconnect between the front end and the backend that resulted in chrome loading forever more often than normal.

Have you checked console log of the browser, do you see any errors there, e.g. like this one?

https://github.com/vaadin/flow/issues/4660