Archive for July, 2011

Grey Line

This was an interesting bug… I was working on a Web application, where Adobe Flex client was sending an instance of an ActionScript WrapperObject to the Java server, which was supposed to invoke some JBDC code to run an SQL Insert statement saving the data from the Java version of WrapperObject in the database. I wrote all the pieces of Flex, Java, and SQL and started Tomcat in Eclipse IDE.

The Web browser displayed my window, I filled out the form populating the ActionScript WrapperObject and pressed the button Save. Nothing happened. No errors and no data inserted in the database.


Well, need to start debugging…Let’s see what could have gotten wrong:
1. I didn’t properly populate the ActionScript WrapperObject
2. I didn’t properly configure the Java class/method so the front end didn’t even call it.
3. I didn’t code the database portion properly.

But why there is no errors? Starting the Flex part in the debug mode quickly revealed that the WrapperObject was properly populated and the asynchronous request to the Java server has been sent.

Great. The next question is, “Have I called the proper endpoint (the destination) on the Java side and if the correct method has been really invoked?” Started an HTTP/AMF sniffer, which confirmed that I was calling a method on the endpoint mapped to the class Customer shown below. On the Java side, the class hierarchy looked as follows:

class _Customer {public boolean saveData( WrapperObject wrapper){
       // an empty method   
   }
}
 
class Customer extends _Customer{
 
   public boolean saveData (WrapperObject wrapper) {
        // the code saving data in DBMS was here
   }
}

Without leaving Eclipse IDE, restarted Tomcat in the debug mode and put a breakpoint in the caller of Java’s saveData. Interesting… The debugger brought me inside the empty method of _Customer.saveData. Do you see any spelling errors in the method signatures? Me neither. This was about time to use a Java annotation @Override, which I was always underestimating. Changed the class Customer to look like this:

class Customer extends _Customer{
 
   @Override
    public boolean saveData (WrapperObject wrapper) {
        // the code saving data in DBMS was here
   }
}

Sure enough, the Java compiler immediately told me that the method saveData has to override the one from the superclass. But I did override it, didn’t I?

The problem was that my project has two different versions of the class WrapperObject located in different packages! The superclass was using the WrapperObject from one package, but the subclass from another! This little annotation caught what my eyes didn’t see. Fixed the import statement in the subclass to properly override the method saveData, re-ran the program and got… an SQL error stating that I have an extra comma somewhere in my Insert statement. But this one is a piece of cake! I was so happy.

Thank you Java @Override – you made my day!From now on I’ll be using this example in all my Java classes.

Yakov Fain

Comments off

 

Grey Line

Flash Player does a very good job in rendering of small to medium data collections. But some enterprise applications need to offer the users to manipulate with tens of thousands of records. One of the projects of recent efforts of Farata Systems is extending standard Adobe Flex collections to make them faster. We call them “lazy collections” because they bring the data to the client in a lazy fashion – only when the user requests them.  This approach allows creating responsive UI that renders large sets of data without causing delays on the UI.
In Flash Player based RIA, non-responsiveness in data manipulations is usually caused by one of the following:
1.    Slow retrieval of the data set from the storage (e.g. slow response from DBMS).
2.    Limited network bandwidth or use of inefficient network protocols
3.    Poor data rendering to the UI components (UI freezes)

In this blog I’ll be talking about the poor data rendering. Typically, we create RIA where Adobe Flex communicates with the server-side Java using the AMF protocol (Java to ActionScript serialization via BlazeDS).  AMF is an efficient HTTP-based protocol for transferring strongly-typed data (Java Data Transfer Objects).  But on the UI side you may start experiencing slowness even on medium-size data grids displaying 500 rows by 50 columns. Add to such grid poorly written item renderers  (with nested containers) and Flash Player quickly becomes a bad guy.

It’s hard to find a Flex enterprise application that doesn’t use DataGrid, and it has to offer responsive UI and smooth scrolling of the data collections that serve as a Model in the MVC-based environment.  When BlazeDS deserilizes large amounts of Java bytes into ActionScript objects, the users may experience a freezing effect, when the UI is not responding to any user’s actions until the serialization is over. The reason being that Flash Player performs this deserialization in the same thread as UI rendering.

When the size of a data collection becomes large (e.g. 30 thousand of ActionScript objects), it’s better to find a way of not bringing all the data at once to Flash Player. This is the main idea of our lazy collections.  It’s about combining smart data pagination and scrolling.

You don’t want to load the entire data set into the Java server’s memory to avoid crashing it. While preparing the screencast that demonstrates advantages of our lazy collections vs. the standard ActionScript ArrayCollection, I had to increase the amount of heap memory on my Tomcat server to prevent Java’s OutOfMemory exceptions – and I was the only user sending data requests to the server! What is a hundred users will cause the server load into memory datasets of a 100Mb each? You need to provide at least 10Gb of memory on the server.

We decided to create data collections that use pagination on the server in conjunction with the smarter collections on the Flex client. We have created beta versions of collections supporting both Halo and Spark Flex components. Even though we are extending standard Flex collections, the processing of the asynchronously arriving data is different in Halo and Spark. Halo’s components are heavier, but smarter when it comes to asynchronous data retrieval. The standard Flex framework (without LCDS support) doesn’t offer any support of lazy loaded collections, and we had to follow our usual path – adding the missing features to BlazeDS.  These are our main collections:

LazyIndexedList – a subclass of ActionScript ArrayList that loads the data objects on demand. For example, the initial data set may contain only a hundred out of fifty thousand objects. If the user scrolls the data in the data grid component and hits the last object of this first hundred, the LazyIndexedList will automatically request the next hundred from the server.

HugeIndexedList adds the ability to unload unused data from memory. This class  monitors the current scrolling position to avoid unloading the data being viewed.

There is some work in progress to complete the functionality required by the Spark’s AsyncListView collection. In the future, these classes will be included in our Clear Toolkit set of components. Meanwhile, you can watch this 9-minute video to see these collections in action.

Valery Silaev

Comments (6)

 

Grey Line

This post is a sequence to our announcement that we taught Adobe AIR to talk to native Android API by placing BlazeDS inside Android. Initially, we embedded BlazeDS into AIR-Android APK (watch this video) to use Google voice recognition for the data entry. The plan was to be able to invoke the following Java code from BlazeDS :

    Intent intent = new Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH);
    intent.putExtra(RecognizerIntent.EXTRA_LANGUAGE_MODEL, RecognizerIntent.LANGUAGE_MODEL_FREE_FORM);
    intent.putExtra(RecognizerIntent.EXTRA_PROMPT, prompt); // We wanted to use Text-to-Speech as well
    startActivityForResult(intent, 12345);

The first challenge was that features like voice recognition, Toast (Android popups) and other dialog functions, are supposed to be run in UI thread vs. a worker thread of the BlazeDS. In particular, startActivityForResult() is a method of Activity class. This was an easy to solve problem, because we could place this code in our own activity and start this activity via Intent.

The real challenge was that the voice recognition software does not return anything until the computer-human interaction is complete. In other words, the Java piece to remote is asynchronous -  you start the Recognizer activity by invoking the function startActivityForResult() and, sometime later,  get notification via an async callback when the results are ready:

public void startVoiceRecognition(int requestCode, String prompt) {
    Intent intent = new Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH);
    intent.putExtra(RecognizerIntent.EXTRA_LANGUAGE_MODEL, RecognizerIntent.LANGUAGE_MODEL_FREE_FORM);
    intent.putExtra(RecognizerIntent.EXTRA_PROMPT, prompt); // Customized prompt
    startActivityForResult(intent, REQUEST_CODE_RECOGNIZE_SPEECH);
    return;
}

The low-hanging solution to this asynchronicity  was to push the results from BlazeDS to a messaging destination that would be listened to by an AIR application:

protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    switch (requestCode) {
        case REQUEST_CODE_RECOGNIZE_SPEECH:
            if (resultCode == RESULT_OK) {
                ArrayList recognizedPhrases = data.getStringArrayListExtra(RecognizerIntent.EXTRA_RESULTS);
                // Now we are ready to pass results back to Air code.
                MessageBroker msgBroker = MessageBroker.getMessageBroker(null);
                AsyncMessage msg = new AsyncMessage();
                msg.setDestination("voiceRecognitionResult");
                msg.setClientId(UUIDUtils.createUUID(true));
                msg.setMessageId(UUIDUtils.createUUID(true));
                msg.setTimestamp(System.currentTimeMillis());
                msg.setBody(recognizedPhrases);
                msgBroker.routeMessageToService(msg, null);
            }
            break;
        }
    super.onActivityResult(requestCode, resultCode, data);
}

This worked, but made the AIR code ugly: we had a RemoteObject with a non-functional result handler plus the messaging destination and a Consumer, which clearly would be replicated for each call of that sort.

LongCalling to the Rescue

And then we realized that this was a déjà vu. We had been there when a stored procedure in one financial application would not return for 3 minutes. We helped that customer without breaking the remoting model. We used the “long calling” instead.

Long calling is Farata’s term to label the customization of a Java adapter and RemoteObject that allows us to quickly receive a dummy return of the original long remote call and reincarnate the mx.rpc.ResultEvent when the real data is ready.  By using a customized RemoteObject the application code becomes agnostic to the fact that remoting operation has “two legs”.  The only requirement that we add is that the name of such remoting method has to end with “AndWait” as in  recognizeVoiceAndWait(). This signals to the ActionScript side that this invocation is a “long calling” and this knowledge is carried forward to the custom Java adapter.

On the Java side, we implemented a PlatformServices object with several methods, most importantly,  startActivityAndWait() and complete(). Here is how we start our own SpeechRecognitionActivity. Notice that the first parameter of the runActivityAndWait() is an intent to start an activity, while the second one is a class of the expected result:

public List recognizeVoiceAndWait(final String prompt) {
    final Intent intent = new Intent(PlatformServices.context(), SpeechRecognitionActivity.class);
    intent.putExtra(RecognizerIntent.EXTRA_PROMPT, prompt);
    return PlatformServices.runActivityAndWait(intent, STRING_LIST);
}
final private static Class> STRING_LIST = null;

The SpeechRecognitionActivity() will start the Recognizer activity precisely like we did in the earlier code snippets. Meanwhile the worker thread that started it will be blocked. It will remain in the blocked state until the onActivityResult() callback from inside the SpeechRecognitionActivity issues the complete() passing exactly the same intent as was used during runActivityAndWait() – this intent is preserved in the onStart() of the SpeechRecognitionAcitivity:

@Override
public void onActivityResult(final int requestCode, final int resultCode, final Intent request) {
    if (requestCode == REQUEST_CODE_RECOGNIZE_SPEECH) {
        final List result;
        if (resultCode == RESULT_OK) {
            result = request.getStringArrayListExtra(RecognizerIntent.EXTRA_RESULTS);
        } else {
            result = null;
        }
        complete(originalIntent, result); // We preserved originalIntent during onStart() of the activity
        finish();
    }
    super.onActivityResult(requestCode, resultCode, request);
}

That’s it. The only limitation is that due to the blocking mechanism of runActivityAndWait() only one at a time call can be executed. Accordingly, the AIR application should avoid sending several “AndWait” requests in one AMF batch.

LongCalling in Action

And, of course, the AIR’s code won’t care about runActivityAndWait and complete() pairs at all. For all it knows, there will be regular remoting calls, albeit ending with “AndWait”:

<?xml version="1.0" encoding="utf-8"?>
<s:View xmlns:fx="http://ns.adobe.com/mxml/2009" 
		xmlns:s="library://ns.adobe.com/flex/spark" 
		xmlns:c="library://ns.cleartoolkit.com/flex/clear"
		title="Voice Recognition"
>
	<fx:Declarations>
		<c:RemoteObject id="service" destination="AndroidJavaDestination"/>
	</fx:Declarations>
	<fx:Script><![CDATA[
 
	import mx.collections.IList;
	import mx.rpc.AsyncToken;
	import mx.rpc.Responder;
	import mx.rpc.events.FaultEvent;
	import mx.rpc.events.ResultEvent;
 
	[Bindable] private var recognizedPhrases:IList;
 
	protected function onTextInputFocusIn(event:FocusEvent):void {
		var target:TextInput = event.currentTarget as TextInput;
		promptAndListen(target.toolTip || target.id, target);
	}
 
	private function promptAndListen(prompt:String, target:Object):AsyncToken {
	   recognizedPhrazes = null;
	   var token:AsyncToken = service.recognizeVoiceAndWait(prompt);
	   token.addResponder(
	     new mx.rpc.Responder(
		onRecognizeVoiceResult, onRecognizeVoiceFault
	     )
	   );
	   token.target = target;
	   return token;
	}
 
	private function onRecognizeVoiceResult(event:ResultEvent):void {
	   recognizedPhrases = event.result as IList;
	   var textInput:TextInput = event.token.target as TextInput;
           var bestMatch:String ;
 
           .... Find the best match from recognizedPhrases  
 
	   textInput.text = bestMatch;
	}				
	]]></fx:Script>
	.  .  .
	<s:Form width="100%">
		<s:FormItem label="Name:">
			<s:TextInput focusIn="onTextInputFocusIn(event)" 
				toolTip="Employee name"/>
		</s:FormItem>
		<s:FormItem label="Phone:">
			<s:TextInput focusIn="onTextInputFocusIn(event)" 
				toolTip="Phone number"/>
		</s:FormItem>
	        .  .  .
	</s:Form>
</s:View>

If you are interested to see this solution in action, I’ll be showing it in August during our fourth annual symposium on enterprise software.

Victor

Comments off

 

Grey Line

The long weekend of non-stop rainy weather presented rare opportunity of organizing the thoughts on the new developments in the industry and prepare to my presentations at the upcoming Fourth Farata Symposium ahead of time. Over the course of two days the consolidated theme emerged – these projects I’ll demo at the symposium are going to be about Prosumer eXperience (PX).

Every element of the software I will be showing has to be upgraded from the plain vanilla Flex/BlazeDS/AIR functionality to adjust and match the target audience. The efforts included creation of a brand new sets of controls, mobile devices integration, modifications in communication protocols, PDF/files integration. Everything needs to be consumer-oriented – with touch interface, simple navigation, integration with voice / phone/location services, contacts, etc. And at the same time it should allow repetitive use by an experienced user in the speed of the back-end systems so UI should not stay in a way of productivity. The conventional approach to the user experience fails. Finally, the same application has to be available on all platforms – PCs, Macs, tablets, TVs – to be really accessible by consumers. Its a long journey, and we are not even a half way there.

Let me define this  “pro” in the term prosumer. The term was coined by futurologist Alvin Toffler in 1980,it’s not commonly used today. Loosely, Toffler’s “proactive consumer” prosumers were consumers who were predicted to each become active to help personally improve or design the goods and services of the marketplace, transforming it and their roles as consumers. Basically it is another term of user driven approach, with user feedback as a main driver for new features/streamlined workflow. Simplicity is the king, and the current level of service desk/community driven software makes the whole process both simple and pragmatic.

The most common usage of the term describes the prosumers as enthusiasts who buy products that fall between professional and consumer grade standards in quality, complexity, or functionality. One of my applications (it’s for insurance salesmen) is specifically targeting 250K-1M people that are in that category. I was amazed to find out how many people in banks, investment companies, etc. fall in this category of users.

Finally, the “producing consumer” prosumer creates goods for their own use and also possibly to sell. Wikipedia states it is uncommon usage. I respectfully disagree. At this stage, we all are producing consumers of Google, Amazon and other services. It would be stupid not to capitalize on users experience in our client’s domain field. My post graduate work was on expert systems. I will be showing how AI built upon rule-based expert system for financial services are affected by facts – statistics and field feedback – to produce the results that actually work.

PX is an upgraded, almost a back-office grade software short of administrative and final approval functions allowing users to achieve more of what they want without training with access to a decision making process of the best in business and with amazingly simple interface. As you decide to go down the rabbit hole, more information used to make decision is exposed allowing you either take different turns or ejecting you into different hole. Think of it as a continuous search based process with context that becomes your product – a kind of a shopping cart. Think of the process of buying a new computer when you start with buying a laptop and end up with a server and tablet or vice versa – it’s based on what you really need.

Prosumers are building their world of information, and these networks (unlike the social ones) can become extremely wide-spread and very sophisticated. While Google+ is aiming @ consolidating facebook, tweeter, meetup and linkedin in a better connected net, its search services or verticals are working across all the users, providing much greater value. Capturing the information and applying similar approach becomes the fashion of the day and a foundation of the new business models.

Sincerey,
Anatole Tartakovsky

Comments off

 

 

doxycycline dosage for lyme disease
viagra australia no prescription
manufacturer of lipitor
low dose doxycycline
viagra brand buy
order levitra online
how can i get viagra
doxycycline staph infection
what alternatives are there to viagra without a prescription?
amoxil pediatric dosing
5 mg propecia buy
alcohol flagyl
cipro overdose
lasix and alcohol
viagra orders
canadian propecia
how long does viagra last
dosage doxycycline
online pharmacy viagra canada
viagra cheap generic
female viagra pills
pfizer zithromax
generic levitra vardenafil
what is lipitor
how does lipitor work
synthroid diarrhea
doxycycline succinate
ingredients in synthroid
quality cialis soft tabs
herbal viagra offers
best price viagra
buy propecia 5mg
buy name brand viagra
c diff flagyl
cheap viagra fast
levitra sales from canada
cialis 5mg
fish doxycycline
is cipro an antibiotic
where can i get cialis
cipro hc
canadian pharmacy viagra legal
c diff flagyl
clomid 100mg twins
american made viagra
free viagra samples uk
doxycycline for bronchitis
buying clomid
natural lasix
viagra female
flagyl gel
doxycycline package insert
doxycycline brand name
cialis online for canadian
doxycycline photosensitivity
lasix edema
viagra deals
clomid weight loss
zithromax 250mg
buy lipitor online
cheapest viagra uk
lasix indications
free cialis
cheapest propecia
5mg cialis
lasix use
effectiveness of clomid
doxycycline and sun
cipro chlamydia
viagra prescription uk
alcohol and cipro
viagra sales uk
strep throat doxycycline
lipitor side affects
internet viagra
lasix cost
online cialis
clomid calculator
buy propecia online without prescription
viagra no prescription overnight
viagra buy uk
clomid dosing
lasix renal failure
100mg clomid twins
lipitor ingredients
american made viagra
50mg viagra retail price
alcohol and zithromax
viagra tablet no prescription needed
amoxil for dogs
propecia orders
propecia 5mg
cialis daily price
female viagra pills
canadian pharmacy discount code viagra
cipro uti dosage
tuna viagra
viagra us pharmacy
cialis buy
buy vardenafil get free viagra
chinese viagra herbal
synthroid interactions
cipro uti
buy viagra without prescription
doxycycline staph
propecia online pharmacy no prescription
propecia without a prescription
cheap cipro
accutane side effects for men
cialis online pharmacy
doxycycline for cats
flagyl for sale
epididymitis doxycycline
buy viagra online without a prescription
canadian pharmacy cialis generic
cialis soft pills
viagra female
propecia generic
flagyl coverage
synthroid headache
cialis brand name
propecia pills
cialis 20 mg 10 pills
doxycycline food
cipro dosing
doxycycline hyc 100mg
cialis dosage
ordering viagra overnight delivery
low price propecia
effects viagra
lasix sulfa allergy
cheap herbal viagra
where to buy propecia
viagra next day delivery uk
zithromax z-pak cost
viagra uk cheap purchase buy
viagra sildenafil citrate
lipitor patent expires
lipitor patent expiration date
uti antibiotics cipro
synthroid and breastfeeding
natural alternatives to viagra
doxycycline blepharitis
lipitor discount card program
how to buy cialis
budget cialis
buy cialis in canada
viagra side effects men
clomid pct
synthroid dosing
best prices on generic cialis
cheap amoxil
lipitor patent expires
flagyl nausea
cipro flagyl
clomid effects
doxycycline bacterial coverage
cost of doxycycline
order clomid online
cipro ophthalmic
viagra delivered one day
recommended sites for cialis in canada
viagra non prescription
discount canadian cialis
how to get viagra online
order levitra
buy cialis profes
doxycycline side affects
mexico viagra without prescription
doxycycline contraindications
where buy viagra
clomid serophene
clomid weight gain
viagra.com
cheap levitra online
buy viagra in australia
us viagra
cialis alternative
effects of lasix
side effects of viagra on men
buy viagra online without prescription
flagyl and cipro
get cialis fast
viagra pills uk
lipitor dangers
propecia sales canadian
uses for doxycycline
buy viagra cialis levitra
viagra fast delivery
synthroid t4
can i buy viagra over the counter in the uk
cipro lawsuit settlements
doxycycline in dogs
best prices for 20 mg levitra
cipro side effect
synthroid hypothyroidism
doxycycline doses
clomid pregnancy symptoms
viagra original
10 mg vardenafil online
clomid 50 mg
purchase viagra online
substitute for lipitor
mrsa doxycycline
zithromax in pregnancy
purchase synthroid
aus viagra
chlamydia zithromax
united states viagra
get viagra online without prescription
cipro otic drops
cheap cialis
lipitor blood pressure
lipitor prices
cialis for less 20 mg
lipitor discount card program
synthroid medication
lasix manufacturer
viagra generic
viagra buy uk 50mg
synthroid calcium
cialis 30 mg
cialis india
brand viagra medicine
accutane canada
viagra on line sale canada pharmacy
cipro back pain
shop online viagra
5 mg cialis
doxycycline 100mg acne
canine doxycycline
hyclate doxycycline
order online viagra
buy viagra and receive it in canada fast
viagra cialis levitra canada
clomid sale
doxycycline heartburn
does propecia work?
buy brand name viagra cost
side effects of flagyl antibiotic
synthroid hypothyroidism
canadian cialis uk
original cialis
generic cialis next day delivery
synthroid 50 mcg
doxycycline for prostatitis
viagra sale online
cipro rash
cheapest viagra prices
cipro travelers diarrhea
online generic viagra
cipro for travelers diarrhea
doxycycline use
nexium and pregnancy
cheap fast generic viagra
online lipitor
viagra online reviews
propecia best price no prescription
canadian pharmacy cialis 5 mg
propecia 5mg. online
lasix nursing considerations
kamagra generic viagra
tuna viagra
genuine cialis online
where can i get viagra
zithromax breastfeeding
buy cialis from canada
levitra sell
but viagra online with mastercard
doxycycline photosensitivity
what does doxycycline hyclate treat
viagra substitute
how to find reputable canadian cialis
viagra prescription uk
canadian pharmacy viagra cheap
lipitor cholesterol
viagra natural
doxycycline alcohol consumption
ordering real levitra