ZK框架:从servlet通知ViewModel

时间:2014-06-24 09:37:45

标签: java servlets mvvm zk

我有一个ZK MVVM应用程序,其标准UI绑定到ViewModel,另外一个servlet用于与外部应用程序通信。我需要执行以下操作:当附加servlet收到http请求时,我需要通知ViewModel并通过server-push向用户显示一些数据。

我尝试通过调用BindUtils.postGlobalCommand并通过使用EventQueues.lookup的事件队列通过GlobalCommand从servlet通知ViewModel,但在这两种情况下,我都收到带有消息的IllegalStateException:不执行

我还尝试在servlet中保留对ViewModel的引用,并直接调用其方法,其中ViewModel试图调用BindUtils.postNotifyChange,但我得到了相同的结果。

有什么方法可以达到预期的行为吗?

1 个答案:

答案 0 :(得分:1)

如评论所述,您应该检查您的架构。但是为了答案,你可以使用Observable java内置模式。

您可以创建一个扩展Observable的服务(假设您正在使用Spring)。然后,您声明一个Window以实现Observer模式并在其桌面上启用服务器推送。最后但并非最不重要的是,您将Window(观察者)注册到服务。

当http请求到达您的servlet时,您将调用服务中的一个方法,该方法将更新其所有观察者(窗口的每个实例)。

这有点棘手。如果您不想警告Window的每个实例,则http请求中必须存在对要更新的实例的引用。如果我假设正确并且http消息是对先前http请求的异步响应,则可以以某种方式嵌入其中的Window Uuid以将其接收回来。通过这种方式,当观察者被触发时,你可以“理解”哪个是初始调用者。

在此之后,您可以使用Executions.schedule来触发特定的ZK事件。

总结:

声明Observable春季服务

@Service
public class MyServiceImpl extends Observable implements MyService {

    @Override
    public void manageResponse(String response) {

      this.setChanged();
      this.notifyObservers(response);               
    }
}

声明Observer ZK窗口(或Component或SelectorComposer)

public class WndMain extends Window implements Observer {

    private static final long serialVersionUID = -216014257162713363L;

    private String _uuid;
    private Desktop _desktop;
    private int _notificationX;
    private MyService myService = "*Locate the service in Spring context*";


    public void onCreate(){
        super.onCreate();
        this._uuid = this.getUuid();
        this._desktop = getDesktop();
        _desktop.enableServerPush(true);
        myService.addObserver(this);
    }

    @Override
    public void update(Observable o, Object arg) {  
        //Check which Observable notified this Observer
        if(o instanceof MyService){
            String response = (String) arg;
            if(response.equals(_uuid)){ 
                //Enter the Desktop and fire the Notification
                Executions.schedule(_desktop, new NotificationEventListener(), new Event("onHttpResponse", this, null));
            }   
        }
    }
    private class NotificationEventListener implements EventListener<Event>{

        @Override
        public void onEvent(Event event) throws Exception {
          if(event.getName().equals("onHttpResponse")){
                Clients.showNotification("Response arrived!", Clients.NOTIFICATION_TYPE_INFO, event.getTarget(), notificationX- 200, 0, 2000);
        }
    }

    public void onClientInfo(ClientInfoEvent event){
        this._notificationX=event.getDesktopWidth()-80;
    }
}

修改

在我的情况下,在JAXB REST servlet中调用manageResponse(String response)方法:

@Path("myPath/servlet/response")
public class MyServiceREST {

    private MyService myService = "*Locate the service in Spring context*";


    @POST
    @Consumes(MediaType.WATHEVER)
    public Wathever receiveResponse(Whatever response){
        if(response!=null){     
            myService.manageResponse(response.getWindowUuid());
        return Response.status(201).build();
        }
        return Response.status(400).build();
    }
}