Hi,
I have been looking over the forums, googling and checking out stackoverflow, but I have not found a solution yet.
I am trying to use server push to update the UI with data fetched asynchronously via a RestFul API calls to a server.
I am using vaadin together with Google’s Gauva library - specifically two features - concurency and eventBus.
It’s all working fine when running in Eclipse’s locally, but once I deploy it on tomcat, after a while I will start getting these UIDetachedExceptions, and they will persisnt - even when starting a new browser.
Basically, I have a ListeningExecutorService initialized and held in the servletContext.
Then my UI class is annotated with @Push(transport = Transport.LONG_POLLING).
I selected long_polling after finding out that our servlet containers will not support websocket, and streaming proved unreliable with IE and FF.
So. My Layouts and components send eventBus events. for example:
listButton.addClickListener(new ClickListener()
{
private static final long serialVersionUID = 1L;
@Override
public void buttonClick(ClickEvent event)
{
((RotisserieUI) UI.getCurrent()).getEventBus().post(new ListAllOrganizationsEvent());
}
});
Then I basically have presenter classes subscribed to the events. When an evant is intercepted, the presenter will submit a Callable to the executorService (again, one, held by the servletContext - and referenced by the presenter super).
Callable will feed a ListenableFuture. The callable makes the restful api call to the server, and returns a json object.
And a FutureCallback will be added to the future, and when the call returns it will update the UI by callind UI.getCurrent().access and calling a method that updates the UI.
Example:
[code]
@Subscribe
public synchronized void listAllOrganizations(ListOrganizationsEvent event)
{
view.showLoadingSearchTab();
ListenableFuture<List> allOrganizationsFuture = executor.submit(new Callable<List>()
{
@Override
public List<SearchOrganizationResultJson> call() throws Exception
{
ItemListJson organizationSearchResultsJson = ApiCaller.listOrganizations(((RotisserieUI) UI.getCurrent()).getAuthenticationHander()
.getSsid());
List<SearchOrganizationResultJson> organizationSearchResultList = (List<SearchOrganizationResultJson>) organizationSearchResultsJson.getItems();
Collections.sort(organizationSearchResultList, new Comparator<SearchOrganizationResultJson>()
{
@Override
public int compare(SearchOrganizationResultJson o1, SearchOrganizationResultJson o2)
{
if (o1.getOrgId() > o2.getOrgId())
{
return 1;
}
return -1;
}
});
return organizationSearchResultList;
}
});
Futures.addCallback(allOrganizationsFuture, new FutureCallback<List<SearchOrganizationResultJson>>()
{
@Override
public void onSuccess(final List<SearchOrganizationResultJson> result)
{
UI.getCurrent().access(new Runnable()
{
@Override
public void run()
{
view.onOrganizationSearchSuccess(result);
}
});
}
@Override
public void onFailure(final Throwable t)
{
UI.getCurrent().access(new Runnable()
{
@Override
public void run()
{
MessageHandler.handleException((Exception) t, "Did not find organizations!", "", false);
view.onOrganizationSearchSuccess(new ArrayList<SearchOrganizationResultJson>());
}
});
}
});
}
[/code]So this is the basic pattern.
As I said, it works. But say, after 30 minutes or so, I start getting UIDetachedException, and even starting fresh on a new browser still gets these. I thought the session and UI are recreated in that case. But obviously the push still goes a non existing UI.
I have no idea what causes the detach, and I don’t know how to make new session updates go to the correct UI.
I really hope someone can help here.
Thanks