我有一个ZK MVVM应用程序,其标准UI绑定到ViewModel,另外一个servlet用于与外部应用程序通信。我需要执行以下操作:当附加servlet收到http请求时,我需要通知ViewModel并通过server-push向用户显示一些数据。
我尝试通过调用BindUtils.postGlobalCommand
并通过使用EventQueues.lookup
的事件队列通过GlobalCommand从servlet通知ViewModel,但在这两种情况下,我都收到带有消息的IllegalStateException:不执行
我还尝试在servlet中保留对ViewModel的引用,并直接调用其方法,其中ViewModel试图调用BindUtils.postNotifyChange
,但我得到了相同的结果。
有什么方法可以达到预期的行为吗?
答案 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();
}
}