Victor
Victor

Reputation: 335

Wicket - Inter-session communication or Create new Request(Cycle) manually

I have some wicket panel store in a static Hashmap from different sessions, i want to do some like if some panel notifies the map, then the map notifies all other panel. for example:

public class PanelMap{
    private static Map<Long, List<MyPanel>> map = new HashMap<Long, List<MyPanel>>();

public static void subscribe(Long id, MyPanel panel){
        if (!map.containsKey(id)){
            map.put(id, new ArrayList<MyPanel>());
        }
        map.get(id).add(panel);
    }
}

public static void notify(Long id, String notification){
        if (map.containsKey(id)){
            List<MyPanel> panels = map.get(id);
            for(MyPanel panel : panels){
                panel.newNotification(notification);
            }
        }
    }
}

In Panel, newNotification(String notification) i want to send request to server and refresh my panel in browser.

public void String newNotification(String notification){
   // do some business logic depends on notification
   onMyRequest();
}

i've made some search among wicket behavior source files and about i found in AbstractDefaultAjaxBehavior i tried to make my own onRequest method inside my wicket panel as follows

private void onMyRequest(){
    AjaxRequestTarget target = ((WebApplication)getApplication()).newAjaxRequestTarget(getPage());
        target.add( _some_wicket_components_ );

        RequestCycle.get().scheduleRequestHandlerAfterCurrent(target);
    }

but all i did is some Ajax error in Wicket Ajax Debug about

 Wicket.Ajax.Call.processComponent: Component with id _containerdiv_ was not found while trying to perform markup update.
ERROR: Cannot find element with id: _someComponentIdOnPanel_

(those components are exist)

How could i send my own request to server (or how can i get valid AjaxRequestTarget to update my components? )

Update: I need inter-session communication.

Upvotes: 1

Views: 910

Answers (2)

Nicktar
Nicktar

Reputation: 5575

To update panels on different user's sessions, you obviously can't use the current AjaxRequestTarget as this in a way represents a single communication between the server and the requesting user of which another user's Browser has no way of knowing. (Very very basically spoken)

You could either use an AjaxSelfUpdatingTimerBehavior to poll for updates. This would generate new AjaxRequestTarget for every user at regular intervals that you can use to attach changed panels to. It's a very basic and simple implementation that will most likely impact your systems performance and generate quite some traffic.

The other way would be to use something like Atmosphere, which is supported by Wicket-Atmosphere (quickstart can be found here) and has some examples over at the wicket-library.com, but that's all I know about this.

Upvotes: 2

jordeu
jordeu

Reputation: 6821

Use Wicket event bus system. Have a look to the "Wicket events infrastructure" chapter of the free Wicket guide.

First you need to create one class to encapsulate the notification and the AjaxRequestTarget and pass them using the events infrastructure.

private class Notification {
    private String message;
    private AjaxRequestTarget target;

    ... constructor, getters, setters...
}

Then the panels that want to recive the event have to override onEvent method, something like this:

public void onEvent(IEvent<?> event) {
    if (event.getPayload() instanceof Notification) {
        Notification notification = (Notification) event.getPayload();

        ... do whatever you want before updating the panel ...

        // Update the panel 
        notification.getTarget().add(this);

    }
}

All the components will recive all the events that are send using Wicket events infrastructure. So you can send the event from any other panel using one method like this

protected void sendMessage(String message, AjaxRequestTarget target) {
    send(getSession(), Broadcast.BREADTH, new Notification(message, target));
}

Remember that if you want to update the components using AJAX, you need to set setOutputMarkupId(true). And if it's a component that can be hidden and you want to make it visible using AJAX, then you need to set setOutputMarkupPlaceholderTag(true).

Upvotes: 1

Related Questions