1
votes

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.

2
does the _some_wicket_components_ exists in the in html page? - fmodos
yes, it does, it's basically an WebMarkupContainer, content container (<div/>) - Victor
Is there are reason you're not using the wicket event bus? - Nicktar
only reason is i don't know what is it :) what is it for? some principal, guide or link ? please - Victor
Could you elaborate on what you mean by 'Intersession communication'? My session affecting the session of another user or my session affecting another of my sessions (how and why would I get multiple sessions?)? Obviously you can't add another users panels to my AjaxRequestTarget. To do this you'd need some kind of push technology like Atmosphere or you'd have to wait until the other user creates an AjaxRequestTarget of his own (maybe using a TimedUpdatingBehaviour. - Nicktar

2 Answers

2
votes

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.

1
votes

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).