gwt AsyncCallback - java - gwt-rpc

I'm doing an asynchronous call to a servlet. In the servlet I am taking some pictures from DB and sending them back to client as Strings. In the Client..in onSuccess(String pictureAsString) method I need to do something with the images after they are loaded and BEFORE going any further. I know the number of images and currently I'm doing some testing like this:
public void onSuccess(String result) {
numberOfReceivedImages = numberOfReceivedImages-1;
//add image as string to a list of images
if(numberOfReceivedImages == 0){
////call method that draws the images from the list }
}
The order in wich the images are drawn should be the order from the list in which the images are stored after receiving them from server, but this order is not kept...and I suppose this is because I'm not receiving all the images by the time I'm drawing them.
Thank you,
any help is appreciated

Are you sure the images are sent in the right order from the server? How do you store them client-side?
I would suggest that you change the signature of your RPC method to somthing like
AsyncCallback<List<String>> callback = new AsyncCallback()
{
public void onSuccess( List<String> result ) {
...
}
...
}
and of course relevant changes on server side. That way, you're guaranteed the same ordering client side as on server side.

Related

How to mock Transport.send() method in this method using MockitoJUnitRunner?

I want to write the testcase for the given method. But there exist a static Transport.sendEmail method.
How can I mock this method using MockitoJunitRunner.
public void sendEmail(final String message, final String contentType) {
final Session session = Session.getDefaultInstance(PROPERTIES, null);
final Multipart mpart = new MimeMultipart();
final MimeBodyPart body = new MimeBodyPart();
try {
body.setContent(message, contentType);
mpart.addBodyPart(body);
Transport.send(createMessage(session, mpart));
LOGGER.info("Email Notification Sent Successfully");
} catch (MessagingException | UnsupportedEncodingException e) {
LOGGER.error("Was not able to send mail", e);
}
So:
Transport.send(createMessage(session, mpart));
that static call means: you can't "control" it using Mockito. Plain and simple. If that call just "passes" in your unit test environment, well, then you can test it, but not verify that the call really took place. Worse, if that call throws some exception in the unit test setup, then heck, what could you do?
Options:
turn to PowerMock(ito) or JMockit, as they allow you to gain control
recommended: improve your design to be easy-to-test
That last idea comes in various flavors:
For example, you could create a minimal interface EmailSenderService that offers a void send(Message whatever) method. Next: you create one implementation of that interface that simply invokes that static method. Now your code that actually has to send that message ... simply gets passed in an instance of EmailSenderService. And within your unit tests, you can now #Mock that interface, and you gain control over it.
Alternatively, you simply deprecate that static method (maybe the whole class), and you design a new "real" EmailSenderService that doesn't rely on static methods.

Multiple REST calls timing out in Spring Boot web application

I created a Spring Boot (1.4.2) REST application. One of the #RestController methods needs to invoke a 3rd party API REST operation (RestOp1) which returns, say between 100-250 records. For each of those records returned by RestOp1, within the same method, another REST operation of the same 3rd party API (RestOp2) must be invoked. My first attempt involved using a Controller class level ExecutorService based on a Fixed Thread Pool of size 100, and a Callable returning a record corresponding to the response of RestOp2:
// Executor thread pool - declared and initialized at class level
ExecutorService executor = Executors.newFixedThreadPool(100);
// Get records from RestOp1
ResponseEntity<RestOp1ResObj[]> restOp1ResObjList
= this.restTemplate.exchange(url1, HttpMethod.GET, httpEntity, RestOp1ResObj[].class);
RestOp1ResObj[] records = restOp1ResObjList.getBody();
// Instantiate a list of futures (to call RestOp2 for each record)
List<Future<RestOp2ResObj>> futureList = new ArrayList<>();
// Iterate through the array of records and call RestOp2 in a concurrent manner, using Callables.
for (int count=0; count<records.length; count++) {
Future<RestOp2ResObj> future = this.executorService.submit(new Callable<RestOp2ResObj>() {
#Override
public RestOp2ResObj call() throws Exception {
return this.restTemplate.exchange(url2, HttpMethod.GET, httpEntity, RestOp2Obj.class);
}
};
futureList.add(future);
});
// Iterate list of futures and fetch response from RestOp2 for each
// record. Build a final response and send back to the client.
for (int count=0; count<futureList.size(); count++) {
RestOp2ResObj response = futureList.get(count).get();
// use above response to build a final response for all the records.
}
The performance of the above code is abysmal to say the least. The response time for a RestOp1 call (invoked only once) is around 2.5 seconds and that for a RestOp2 call (invoked for each record) is about 1.5 seconds. But the code execution time is between 20-30 seconds, as opposed to an expected range of 5-6 seconds! Am I missing something fundamental here?
Is the service you are calling fast enough to handle that many requests per second?
There is an async version of RestService is available called AsyncRestService. Why are you not using that?
I would probably go like this:
AsyncRestTemplate asyncRestTemplate = new AsyncRestTemplate(new ConcurrentTaskExecutor(Executors.newFixedThreadPool(100)));
asyncRestTemplate.exchange("http://www.example.com/myurl", HttpMethod.GET, new HttpEntity<>("message"), String.class)
.addCallback(new ListenableFutureCallback<ResponseEntity<String>>() {
#Override
public void onSuccess(ResponseEntity<String> result) {
//TODO: Add real response handling
System.out.println(result);
}
#Override
public void onFailure(Throwable ex) {
//TODO: Add real logging solution
ex.printStackTrace();
}
});
Your question involves two parts :
multiple API callbacks asynchronously
handle timeouts (fallback)
both parts are related as you've to handle the timeout of each call.
you may consider use Spring Cloud (based on spring boot) and use some out of the box solution based on OSS Netflix stacks.
The first (timeouts) on should be a circuit breaker hystrix based on feign client
The second (multiple requests) this is an architecture issue, using native Executors isn't a good idea as it will not scale and has a huge maintenance costs. You may relay on Spring Asynchrounous Methods you'll have better results and fully spring compliant.
Hope this will help.

How to Dispose an InMemory Cached result in ServiceStack

I have a service in my ServiceStack API to handle image results, by implementing IStreamWriter WriteTo(stream). Works great.
To optimize the processing I am adding support for the InMemory Cache, with a TimeSpan to expire the results. My concern is related to IDispose. Prior to cache implementation I was using IDispose to dispose the result object and its image after returning, but with inmemory cache it cannot implement IDispose, otherwise the data will be wiped before it is refetched from cache.
Question is how, or where, to implement the disposal of the cached results? Will the cache dispose the items on expiration? If so, how to implement Dispose only for calls from cache manager, but not from http handler.
public class ImageResult : IDisposable, IStreamWriter, IHasOptions
{
private readonly Image image;
public void WriteTo(Stream responseStream)
{
image.Save(responseStream, imgFormat);
}
public void Dispose()
{
// if we dispose here, will be disposed after the first result is returned
// want the image to be disposed on cache expiration
//if (this.image != null)
// this.image.Dispose();
}
}
public class ImageService : AssetService
{
public object Get(ImageRequest request)
{
var cacheKey = ServiceStack.Common.UrnId.Create<ImageRequest>(request.id);
if (Cache.Get<ImageResult>(cacheKey) == null)
{
Cache.Set<ImageResult>(cacheKey, GetImage(request), TimeSpan.FromMinutes(1));
}
return Cache.Get<ImageResult>(cacheKey);
}
[...]
}
From a quick look at ServiceStack's InMemoryCache you can see there's no event or callback to hook into for cache entry expiration. Consider using System.Runtime.Caching.MemoryCache which gives you similar caching capabilities, plus specifically you can use a change monitor for callback on expiration and/or removal.
Another alternative: create your own from SS's cache source code to provide you with a callback.
Once you have a callback in place, you could call Dispose() from there - but as you said you don't want the ImageResult to be disposable, instead allow access to its Image property and dispose that from the expiration callback yourself. You could wrap a class around .net's image to allow for unit testing (avoid having to use a real image object in tests).
EDIT: actually.. see below(*), this would create a mess.
On another note, I would make some slight changes to your Get() method. The last call to Cache.Get() is superfluous. Even though you're using an in-memory cache you'd still want to minimize access to it as it's potentially slower than it may seem (needs to use locks to synchronize in-memory access from multiple threads).
var imageResult = Cache.Get<ImageResult>(cacheKey);
if (imageResult == null)
{
imageResult = GetImage(request);
Cache.Set<ImageResult>(cacheKey, imageResult, TimeSpan.FromMinutes(1));
}
return imageResult;
(*) Just realized you could have a request getting the ImageResult from the cache, and then an instance later, before it writes anything to the target (response) stream, it expires and gets disposed. Nasty. Instead, let .net handle this for you: instead of making ImageResult implement IDisposable, create a destructor in which you dispose the internal Image object. This will work with SS's in memory cache:
~ImageResult()
{
image.Dispose();
}

How to get information/data from platformRequest() in J2ME?

I want to implement a behavior similar to Whatsapp, where when the user can upload an image. I tried opening the images in my app, but if the image is too large, I will have an out of memory error.
To solve this, I'm opening forwarding the images to be open in the phone's native image viewer using the platformRequest() method.
However, I want to know how is it Whatsapp modifies the phone's native image viewer to add a "Select" button, with which the user selects the image he wants to upload. How is that information sent back to the J2ME application and how is the image resized?
Edit:
I tried this in two different ways, both of which gave me the OOME.
At first, I tried the more direct method:
FileConnection fc = (FileConnection) Connector.open("file://localhost/" + currDirName + fileName);
if (!fc.exists()) {
throw new IOException("File does not exists");
}
InputStream fis = fc.openInputStream();
Image im = Image.createImage(fis);
fis.close();
When that didn't work, I tried a more "manual" approach, but that gave me an error as well.
FileConnection fc = (FileConnection) Connector.open("file://localhost/" + currDirName + fileName);
if (!fc.exists()) {
throw new IOException("File does not exists");
}
InputStream fis = fc.openInputStream();
ByteArrayOutputStream file = new ByteArrayOutputStream();
int c;
byte[] data = new byte[1024];
while ((c = fis.read(data)) != -1) {
file.write(data, 0, c);
}
byte[] fileData = null;
fileData = file.toByteArray();
fis.close();
fc.close();
file.close();
Image im = Image.createImage(fileData, 0, fileData.length);
When I call the createImage method, the out of memory error occurs in both cases.
This varies with the devices. An E72 gives me the error with 3MB images, while a newer device will give me the error with images larger than 10MBs.
MIDP 2 (JSR 118) does not have API for that, you need to find another way to handle big images.
As for WhatsApp, it looks like they do not rely on MIDP in supporting this functionality. If you check the Wikipedia page you'll note that they don't claim general Java ME as supported platform, but instead, list narrower platforms like Symbian, S40, Blackberry etc.
This most likely means that they implement "problematic features" like one you're asking about using platform-specific API of particular target devices, having essentially separate projects / releases for every platform listed.
If this feature is really necessary in your application, you likely will have to do something like this.
In this case, consider also encapsulating problematic features in a way to make it easier to switch just part of your source code when building it for different platforms. For example, Class.forName(String) can be used to load platform specific implementation depending on target platform.
//...
Image getImage(String resourceName) {
// ImageUtil is an interface with method getImage
ImageUtil imageUtil = (ImageUtil) Class.forName(
// get platform-specific implementation, eg
// "mypackage.platformspecific.s40.S40ImageUtil"
// "mypackage.platformspecific.bb.BBImageUtil"
// "mypackage.platformspecific.symbian.SymbialImageUtil"
"mypackage.platformspecific.s40.S40ImageUtil");
return imageUtil.getImage(resourceName);
}
//...

How can I get GWT RequestFactory to with in a Gadget?

How can I get GWT RequestFactory to with in a Gadget?
Getting GWT-RPC to work with Gadgets is explained here.
I'm looking for a analogous solution for RequestFactory.
I tried using the GadgetsRequestBuilder, so far I've managed to get the request to the server using:
requestFactory.initialize(eventBus, new DefaultRequestTransport() {
#Override
protected RequestBuilder createRequestBuilder() {
return new GadgetsRequestBuilder(RequestBuilder.POST,
getRequestUrl());
}
#Override
public String getRequestUrl() {
return "http://....com/gadgetRequest";
}
});
But I end up with the following error:
java.lang.StringIndexOutOfBoundsException: String index out of range: 0
at java.lang.String.charAt(String.java:694)
at com.google.gwt.autobean.server.impl.JsonSplittable.create(JsonSplittable.java:35)
at com.google.gwt.autobean.shared.impl.StringQuoter.split(StringQuoter.java:35)
at com.google.gwt.autobean.shared.AutoBeanCodex.decode(AutoBeanCodex.java:520)
at com.google.gwt.requestfactory.server.SimpleRequestProcessor.process(SimpleRequestProcessor.java:121)
The general approach for sending a RequestFactory payload should be the same as RPC. You can see the payload that's being received by the server by running it with the JVM flag -Dgwt.rpc.dumpPayload=true. My guess here is that the server is receiving a request with a zero-length payload. What happens if you set up a simple test involving a GadgetsRequestBuilder sending a POST request to your server? Do you still get the same zero-length payload behavior?

Resources