remote pupulation of GWT listbox - gwt

I am trying to use RPC calls for fetching data from the Server-->DB and then populate my client side widgets like ListBox, Grid etc. The problem is that since the calls are asynchronous, it cannot be guaranteed that the client side runtime will wait for the server calls to come back and then populate the widgets using the data from the callback result. Is there a way to do this?
regards,
J

By design, there is no way to make a synchronous request in GWT. You can, however refrain from showing the widgets (and perhaps display a spinner) until the data has returned from the server. A way to do this would be to make the widgets visible in a method that is called from the AsyncCallback you used when getting the data from the server.
An example follows (in practice, you'd probably do this at a form level, as opposed to a widget level, but you get the idea).
AsyncCallback<List<Option>> callback = new AsyncCallback<List<Option>>() {
public void onFailure(Throwable caught) {
processError(caught);
}
public void onSuccess(List<Option> result) {
updateListBox(result);
showListBox();
}
};
myRemoteService.getOptions(callback);

You may display a modal dialog box (with a message like "fetching data", or anything fancier), when you start fetching data, and then you may close the dialog box when your RPC call terminates. Another approach is to use a small loading panel that you activate/de-activate as needed: an example is here

Related

How do I call a method on my ServiceWorker from within my page?

I have a ServiceWorker registered on my page and want to pass some data to it so it can be stored in an IndexedDB and used later for network requests (it's an access token).
Is the correct thing just to use network requests and catch them on the SW side using fetch, or is there something more clever?
Note for future readers wondering similar things to me:
Setting properties on the SW registration object, e.g. setting self.registration.foo to a function within the service worker and doing the following in the page:
navigator.serviceWorker.getRegistration().then(function(reg) { reg.foo; })
Results in TypeError: reg.foo is not a function. I presume this is something to do with the lifecycle of a ServiceWorker meaning you can't modify it and expect those modification to be accessible in the future, so any interface with a SW likely has to be postMessage style, so perhaps just using fetch is the best way to go...?
So it turns out that you can't actually call a method within a SW from your app (due to lifecycle issues), so you have to use a postMessage API to pass serialized JSON messages around (so no passing callbacks etc).
You can send a message to the controlling SW with the following app code:
navigator.serviceWorker.controller.postMessage({'hello': 'world'})
Combined with the following in the SW code:
self.addEventListener('message', function (evt) {
console.log('postMessage received', evt.data);
})
Which results in the following in my SW's console:
postMessage received Object {hello: "world"}
So by passing in a message (JS object) which indicates the function and arguments I want to call my event listener can receive it and call the right function in the SW. To return a result to the app code you will need to also pass a port of a MessageChannel in to the SW and then respond via postMessage, for example in the app you'd create and send over a MessageChannel with the data:
var messageChannel = new MessageChannel();
messageChannel.port1.onmessage = function(event) {
console.log(event.data);
};
// This sends the message data as well as transferring messageChannel.port2 to the service worker.
// The service worker can then use the transferred port to reply via postMessage(), which
// will in turn trigger the onmessage handler on messageChannel.port1.
// See https://html.spec.whatwg.org/multipage/workers.html#dom-worker-postmessage
navigator.serviceWorker.controller.postMessage(message, [messageChannel.port2]);
and then you can respond via it in your Service Worker within the message handler:
evt.ports[0].postMessage({'hello': 'world'});
To pass data to your service worker, the above mentioned is a good way. But in case, if someone is still having a hard time implementing that, there is an other hack around for that,
1 - append your data to get parameter while you load service-worker (for eg., from sw.js -> sw.js?a=x&b=y&c=z)
2- Now in service worker, fetch those data using self.self.location.search.
Note, this will be beneficial only if the data you pass do not change for a particular client very often, other wise it will keep changing the loading url of service worker for that particular client and every time the client reloads or revisits, new service worker is installed.

Using class selectors to get Dojo widgets: Good or Bad?

I am using Dojo 1.9 for a web application I'm writing using WebSockets. When the client receives a message from the server, I need to update certain widgets with the data received.
// sock is the client-side of the websocket
sock.onmessage = function (dataIn) {
// clientManager defined elsewhere
clientManager.fireMessageReceived(dataIn);
};
Here's my problem: At the point that I receive the data, I don't have the ID's, DOM nodes or widgets to access the properties/values to be updated. clientManager deals specifically with sock events and doesn't have any specific knowledge of the widgets that its data will be updating. Also, it's possible to have multiple instances of the same widget, so I think trying to maintain a collection of existing widgets (or ID's) as a property of the client manager could get hairy pretty quickly.
So, my solution was to use CSS classes.
I created an empty class and assigned it to my widget:
.myXYZWidget {
}
so that in my fireMessageReceived function, I can use dojo/query to find it:
var myXYZWidgets = dojo.query(".myXYZWidget");
var i;
for (i = 0; i < myXYZWidgets.length; i++) {
var xyzWidget = registry.byNode(myXYZWidgets[0]);
... // Now I have my Dojo widget, I can upate to my heart's content
}
This works and I'm not seeing any major downsides to doing this, but is this ok or is this bad bad bad? Can anyone in the community that has a knowledge of Dojo confirm this solution or suggest a better one?
A class is not necessarily CSS. So you're not using CSS to get Dojo widgets, you're just accessing the widgets by a selector/query.
If I think about your problem I would think about the publisher/subscriber pattern where your websocket is your publisher (since it receives data and needs to emit it to your widgets) and your widgets are your subscribers.
Subscriber(s) (widgets)
Luckily for you dojo has something for it and it's called the dojo/topic module. When you create your widget, you somehow want to make sure that it's a subscriber of the data your websocket receives. To do that, I would do something like this (I'm using a dijit/form/Select in my example, but you can rewrite it to whatever you want):
lang.mixin(mySelect, {
__getData: function(data) {
this.addOption(data);
}
});
mySelect.own(topic.subscribe("my/event", lang.hitch(mySelect, '__getData')));
What happens here is pretty easy (altough it might look hard). The first thing I do is to make sure my widget has an extra method called __getData. This method will receive the data from the websocket and will update its own based on the data.
Then I make sure the widget is subscribed to events with the name my/event (you will see what this means in a while).
Publisher (websocket)
Then at the level of your websocket code, you want to publish to a topic called my/event so that your widgets will know about it.
You can do that like this:
topic.publish("my/event", myData);
Where myData is the data you received from your websocket.
So now the flow is complete. Your websocket code will emit data to who wants to listen. The listeners (widgets) will use the data and do something with it, for example adding items to themself.
I also made a JSFiddle showing a complete example. This solution might look more complex, but I think it's pragmatically more correct.

ASP.NET MVC2 AsyncController: Does performing multiple async operations in series cause a possible race condition?

The preamble
We're implementing a MVC2 site that needs to consume an external API via https (We cannot use WCF or even old-style SOAP WebServices, I'm afraid). We're using AsyncController wherever we need to communicate with the API, and everything is running fine so far.
Some scenarios have come up where we need to make multiple API calls in series, using results from one step to perform the next.
The general pattern (simplified for demonstration purposes) so far is as follows:
public class WhateverController : AsyncController
{
public void DoStuffAsync(DoStuffModel data)
{
AsyncManager.OutstandingOperations.Increment();
var apiUri = API.getCorrectServiceUri();
var req = new WebClient();
req.DownloadStringCompleted += (sender, e) =>
{
AsyncManager.Parameters["result"] = e.Result;
AsyncManager.OutstandingOperations.Decrement();
};
req.DownloadStringAsync(apiUri);
}
public ActionResult DoStuffCompleted(string result)
{
return View(result);
}
}
We have several Actions that need to perform API calls in parallel working just fine already; we just perform multiple requests, and ensure that we increment AsyncManager.OutstandingOperations correctly.
The scenario
To perform multiple API service requests in series, we presently are calling the next step within the event handler for the first request's DownloadStringCompleted. eg,
req.DownloadStringCompleted += (sender, e) =>
{
AsyncManager.Parameters["step1"] = e.Result;
OtherActionAsync(e.Result);
AsyncManager.OutstandingOperations.Decrement();
}
where OtherActionAsync is another action defined in this same controller following the same pattern as defined above.
The question
Can calling other async actions from within the event handler cause a possible race when accessing values within AsyncManager?
I tried looking around MSDN but all of the commentary about AsyncManager.Sync() was regarding the BeginMethod/EndMethod pattern with IAsyncCallback. In that scenario, the documentation warns about potential race conditions.
We don't need to actually call another action within the controller, if that is off-putting to you. The code to build another WebClient and call .DownloadStringAsync() on that could just as easily be placed within the event handler of the first request. I have just shown it like that here to make it slightly easier to read.
Hopefully that makes sense! If not, please leave a comment and I'll attempt to clarify anything you like.
Thanks!
It turns out the answer is "No".
(for future reference incase anyone comes across this question via a search)

Employing GWT's RequestFactory within Activities

My CustomerActivity class happens also to be a presenter in the MVP sense. In response to actions by the user, the following code is called:
context.update(customer).fire(new Receiver<CustomerProxy>() {
public void onSuccess(CustomerProxy response) {
// set the view according to the response
}
});
When the above code executes, two things happen:
I receive an updated copy of the Customer, with which I can refresh the state of the view
An EntityProxyChange event is fired
The CustomerActivity listens for EntityProxyChange events because other Activities also make changes to customer records, and I want to keep the CustomerActivity up-to-date.
EntityProxyChange.registerForProxyType(eventBus, CustomerProxy.class,
new EntityProxyChange.Handler<CustomerProxy>() {
public void onProxyChange(EntityProxyChange<CustomerProxy> event) {
fetchCustomer(event.getProxyId());
// ...but what if it was me that made the change?
}
});
Since theupdate method already returns an up-to-date Customer, I don't need to fetch the customer again during processing of the EntityProxyChange; and I don't want to incur the cost of another call to the server if I can avoid it.
I was hoping that the EntityProxyChange class would provide me with the entity's version number, which I could compare with the version of the customer I have cached. No dice.
I suppose I can set some kind of inTheMiddleOfAnUpdateOperation flag, and check it before fetching the customer. Is that what people are doing? The idea makes me gag just a little bit. Can you suggest a better way to write an activity that listens for changes and makes changes to the same entity types?
I'm not sure this would work, but you could try to create another event bus :
final EventBus customerActivityEventBus = new SimpleEventBus();
Initialize a new RequestFactory with this eventBus and use it in the CustomerActivity.
customerActivityRequestFactory = GWT.create(CustomerRequestFactory.class);
customerActivityRequestFactory.initialize(customeActivityEventBus);
CustomerRequest context = customerActivityRequestFactory.customerRequest();
Your CustomerActivity will still listen to change events from the main eventBus but will not see the events it fired.
In your other activities, listen to events either only from the customerActivityEventBus or from both, depending on what you want.
Of course, keep only one main eventBus to use for events that are not from a Request Factory (ie. ActivityManager, PlaceHistoryHandler, etc ..)

Send a empty Message or Notification with MVVM toolkit light

I'm using the MVVM Light Toolkit. I could not find any Ctor of Messenger or Notification class to send a empty message.
ViewModel1:
private int _selectedWeeklyRotation;
public int SelectedWeeklyRotation
{
get { return _selectedWeeklyRotation; }
set
{
if(_selectedWeeklyRotation == value)
return;
_selectedWeeklyRotation = value;
this.OnPropertyChanged("SelectedWeeklyRotation");
if(value > 1)
Messenger.Default.Send();
}
}
ViewModel2:
Ctor:
Messenger.Default.Register(this, CreateAnotherTimeTable);
private void CreateAnotherTimeTable()
{
}
I just need to send a Notification to another ViewModel, no sending of data at all.
Is that possible with MVVM Light Toolkit library?
Unless I'm misunderstanding something, couldn't you accomplish this by creating and sending a custom "signal message" type via the Messenger?
public class WeeklyRotationSignal {}
Messenger.Default.Send(new WeeklyRotationSignal());
Then register to that in another view model:
Messenger.Default.Register<WeeklyRotationSignal>(this, msg => doWork);
You can try sending a simple message with a string tag and receive that message by matching the string tag. Something like this:
Sender portion of the code located possibly in something like ViewModel1.cs
Messenger.Default.Send<string>("Dummy text message", "String_ToHelpMatchTheMsg");
Receiving end portion of the code responding to that message above, possibly located in some other file, something like ViewModel2.cs
...
Messenger.Default.Register<string>(this, "String_ToHelpMatchTheMsg", executeThisFunction);
private void executeThisFunction(string strMsg)
{
//your code would go here to run upon receiving the message
// The following line will display: "Dummy text message"
System.Windows.Browser.HtmlPage.Window.Alert("msg passed: " + strMsg);
}
Please note that you dont have to do anything with the text message that is passed around with the messaging code above. Just one part of the code sending some ping to another part of the code to ask some other section to execute some code. The important string is the one where I used "String_ToHelpMatchTheMsg" because that is the key used to match the sender and the receiver. Almost like creating your own quasi-event, once the Send method runs, the Register method is notified and fire its own function to run also.
I used this with a Close button on a Child Window to close it. The Close button on the View of the Child Window binds to a relay command on its childWindowViewModel. That relay command has the code above to send a message to the ParentViewModel. The Register portion on the ParentViewModel responds to that message by firing a method that closes the ChildWindow which was initially instantied from that parentViewModel.
Once you get more familiar with messaging, there are more attributes that you will be able to use so that the receiver can call back the sender to give a status or some data back. Look for Delegates and lambda function to achieve this.
All this to avoid placing code in the code behind to close the child window! :-)
Use as you see fit.
Cheers.
Mario
There really isn't a way to accomplish this and in someways defies the point of the messenger class. I didn't want to write a your doing it wrong post, but I feel I am stuck. The way the messenger class works is that you have two parties that both subscribe to the same concept, its an observer model. Without that similar concept or message there really isn't a way to tie the two objects together. The generic message whether a simple string or custom message act as the meeting point of the Subscribing and Publishing classes.
If the ViewModel publishing knows the type of ViewModel its trying to Send to it could...
Messenger.Default.Send<Type>(typeof(ViewModelToSendTo);
This would act as a very simple interaction point, you also wouldn't have to create a custom class. Some purist may have an issue with this approach as it couples the publishing class to the subscriber.
I don't think that it is possible and frankly I don't see the point of having that kind of message. You could just as well send a string "SelectedWeeklyRotation". It seems strange to have an empty message that has some kind of meaning as you increase the number of broadcast messages - and receivers in your application.
In the version of MVVM Light that I'm using it is not even possible to send an empty message.
However I did see a method in the ViewModelBase that is :
// Update bindings and broadcast change using GalaSoft.MvvmLight.Messenging
RaisePropertyChanged(MyPropertyPropertyName, oldValue, value, true);
This might be of interest for you.