Search code examples
ajaxwebsocketwicketjava-websocket

How to re-render Wicket component after the Event reception


I have a Wicket component which is listening for some event (IEvent). If such event arrives, I want to re-render the component with a changed model. There are no active controls on the page, like AjaxLink, which can trigger the re-rendering.

Is there a way to refresh such kind of component?

I was thinking to somehow trigger an AJAX request from the onEvent method and add an AjaxBehavior to the mentioned component. But I don't know, how to trigger the AJAX request.

public class PersonPanel extends Panel implements Observer {

    private WebMarkupContainer wrapper;

    public PersonPanel(String id) {
        super(id);

        setDefaultModel(new CompoundPropertyModel<PersonInfo>(getModel()));

        wrapper = new WebMarkupContainer("wrapper");
        wrapper.setOutputMarkupId(true);
        add(wrapper);

        wrapper.add(new Label("personID"));
        // some more content
    }

    private IModel<PersonInfo> getModel() {
        return new LoadableDetachableModel<PersonInfo>() {
            @Override
            protected PersonInfo load() {
                // model loading logic
            }
        };
    }

    @Override
    public void onEvent(IEvent<?> event) {
        logger.debug("\n   Person Panel received an Event: " + event.getPayload());

        // Re-rendering of "wrapper" should be triggered from here.
    }

    @Override
    public void update(Observable observable, Object o) {
        send(this, Broadcast.EXACT, "Observable cache has changed.");
    }
}

Solution

  • Here is the solution, thanks to hint from martin-g, solved via WebSockets. See the methods update and onEvent, plus added WebSocketBehavior on the component:

    public class PersonPanel extends Panel implements Observer {
    
        private WebMarkupContainer wrapper;
    
        public PersonPanel(String id) {
            super(id);
    
            setDefaultModel(new CompoundPropertyModel<PersonInfo>(getModel()));
    
            wrapper = new WebMarkupContainer("wrapper");
            wrapper.setOutputMarkupId(true);
            add(wrapper);
    
            wrapper.add(new Label("personID"));
            // some more content
    
            add(new WebSocketBehavior() {
            });
    
            observableCache.addObserver(this);
        }
    
        private IModel<PersonInfo> getModel() {
            return new LoadableDetachableModel<PersonInfo>() {
                @Override
                protected PersonInfo load() {
                    // model loading logic
                }
            };
        }
    
        @Override
        public void onEvent(IEvent<?> event) {
            if (event.getPayload() instanceof WebSocketPushPayload) {
                WebSocketPushPayload wsEvent = (WebSocketPushPayload) event.getPayload();
                wsEvent.getHandler().add(wrapper);
            }
        }
    
        @Override
        public void update(Observable observable, Object o) {
            WebSocketSettings webSocketSettings =
                WebSocketSettings.Holder.get(getApplication());
            WebSocketPushBroadcaster broadcaster =
                new WebSocketPushBroadcaster(webSocketSettings.getConnectionRegistry());
            broadcaster.broadcastAll(
                    getApplication(),
                    new WebSocketMessage("WebSocket message from the PersonPanel."));
        }
    
    }
    

    You can find a full running example project, implemented in Wicket 8 and Gradle on Bitbucket: