ClearDS for Android

Clear DataServices (ClearDS) is a free productivity tool that compliments Adobe AIR Native Extensions(ANE) for Android devices. It allows to embed BlazeDS into the AIR-based Android application.

Why ClearDS?

ClearDS has been designed for two purposes. Similar to ANE, it allows to code part of your application in Java with full access to Android SDK. In addition, we can turn an Android device into a server, broadening possibilities for application architectures.

Prior to ANE, simple features like Android Toast and Status Bar notifications as well as advanced ones like Text-to-Speech or Speech Recognition were out of reach for ActionScript coders. ClearDS allows you to embed the Android code into a Java class hosted by a servlet container with  BlazeDS and remote to that class with standard and familiar <s:RemoteObject>. There is no dependency on AIR version and you can natively debug the Java portion of your application using Android Eclipse plugin.

By the same token embedding of BlazeDS into  APK turns your application into a server. Now any computer on the same LAN or VPN can remote to your mobile device. Imagine a scenario where your mobile phone is used as a signature pad where you sign to complete an insurance application or  a financial transaction. Here are some other use cases for your mobile phone:

– bar code reader
– better camera for your notebook,
– voice data/entry gadget that renders alphanumeric keyboard useless, eliminating costly clerical mistakes.

How Does It Work?

We fine tuned BlazeDS to be compatible with a set of core Java classes used by Android. To enable HTTP traffic between the SWF and Java portions of your APK we employed Winstone Servlet Container. Since Android APK generated by the Flash Builder generates a single-activity application, we extended this (activity) class. This allowed us to start the ClearDSService when the activity gets created. The service, in turn, starts the Winstone Servlet container. This allows your SWF-based ActionScript code to remote to your Java code within the boundaries of the same APK.

To make the developers’ life easy, we created the ClearDS Eclipse plugin.When you create a new ClearDS project you effectively create two projects: a Flash Mobile project and Android Java mobile project. These projects are related: the additional builder script of the Flash project contributes the SWF as an asset to the Android project. Then you just deploy your Android project the same was as the users of Android Eclipse plugin do. You develop MXML/ActionScript code in Eclipse’s Flash project,  and accordingly,  the Java code in the Android project.

Is ClearDS a Right Approach for You?

Adobe’s AIR Native Extension is a door opener to the world of native APIs of mobile devices. If you find an ANE with the functionality you need – just use it. Unfortunately, there is no way to debug mobile ANE. On the other hand, if you choose the ClearDS route, you will be able to debug the Java code using standard Android ADT Eclipse plugin.

So, as long as you feel comfortable writing Flex and Java code, download the ClearDS plugin and use it right away.

You can also watch this 10-minute screencast of ClearDS plugin in action here.

We also started added the ClearDS-related content to the wiki page of Clear Toolkit located at this URL. You may also subscribe for our new video channel at Youtube.

Victor

Taming BlazeDS for Android with LongCalling

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 :
[quickcode:noclick] 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);
[/quickcode]

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&gt; 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

Presentation slides from Flash and the City 2010

Yesterday, I’ve presented at Flash and the City conference in New York City on Clear Toolkit, as an open source alternative to Adobe LiveCycle Data Services. Half of the presentation was about features and tools od Clear Toolkit 3.2, and then I’ve demonstrated our new Flex 4 spark-based DataForm container with convenient layout manager, data provider and both form and form item level validators.

The last portion of the presentation was about how to deal with unreliable messaging of BlazeDS. Interestingly enough, some people from the audience were complaining that even in LiveCycle Data Services 3, the reliable messaging part is not documented and it’s hard to get support from Adobe. If you don’t know what unreliable AMF messaging is, read this post. We already had a number of projects started form a phone call, “One of our clients doesn’t receive responses to RemoteObject requests…once in a while. Others seems to be fine. Can you help?” Yes we can.

You can download the presentation slides here.
There were no video recording crew at the conference, but due to multiple requests, I’ll record this presentation and publish it as a screencast in early June.

My special thanks to Adobe for raising LCDS prices – this means more business for us as more and more corporate clients are looking for reasonably priced solution and architect their projects using BlazeDS.
Farata Systems will gladly help our clients in building robust, scalable, and reliable Flex-BlazeDS-Java applications.

If you are new to Flex, consider taking this 5-day live online training course.

Yakov Fain

Open source alternatives to LiveCycle Data Servcies

Development of enterprise Flex/Java rich Internet applications benefits from using automated data integration solutions and productivity tools. Currently Adobe offers LiveCycle Data Services ES2 (LCDS) and open source BlazeDS 3.  While LCDS is certainly a great piece of software for those who are looking to support thousands concurrent users via the most efficient communication protocols, its high licensing cost makes LCDS not affordable for the vast majority of the enterprise applications let alone small businesses and startups.

If you are looking for an alternative solution for to integrate Flex and Java EE layers consider using GraniteDS, WebOrb, and Clear Toolkit. The first two products offer their own implementation of the AMF protocol, and Clear Toolkit uses the AMF libraries that come with BlazeDS . If you are looking for an open source implementation of the Real-Time Messaging Protocol (RTMP), the Red5 server (currently in version 0.7) may be your option.


The feature matrix below lists compares LCDS, BlazeDS, and open source Clear Toolkit. This feature matrix was created using the data from LCDS/BlazeDS comparison chart published by Adobe .

The current version of Clear Toolkit is 3.2.1. The features that are currently not available but will be implemented in Clear Toolkit version 4 by the end of 2010 and are marked as v4 in the chart below.

 

Disclaimer. I’m one of the creators of Clear Toolkit. But if the owners of GraniteDS, WebOrb, and Red5 would like to be listed here, please let me know, and I’ll gladly update this feature matrix.

Feature Matrix: Adobe Live Cycle Data Services ES2, BlazeDS 3, Clear Toolkit 3+


Feature

BlazeDS 3

BlazeDS+Clear Toolkit

LCDS ES2

RPC services

Java remoting/AMF

X

X

X

AJAX to Java

X

X

X

WS/JSON proxy

X

X

X

Messaging

Servlet-based messaging (hundreds of clients per CPU)

X

X

X

Servlet-based NIO messaging (thousands of clients per CPU)

X*

Java NIO high-performance messaging (thousands of clients per CPU)

X

Real Time Messaging Protocol (RTMP)

X

Data throttling

v4

X

Reliable communications

v4

X

Data Management

Transaction (batch processing)

X

X

Data paging

v4

X

Lazy loading (on demand)

v4

X

Hierarchical data collections X X

Conflict resolution and synchronization

X

X

SQL adapter

X

X

Hibernate adapter

v4

X

Fiber-aware assembler

v4**

X

Offline Web applications

X

Development and deployment

Spring integration support

X

v4

X

Adobe Flash® Builder™ modeling plug-in

X

Enterprise support

X

X

RIA PDF generation

X***

X

WSRP portal integration

X

Load/stress testing tool

X

Source code available

X

X

Edge server

X

Enterprise support plans

X

X

Productivity Tools

Generator of CRUD application

X

X

Generator of ActionScript data transfer object based on their Java peers

X

X

Generator of ANT script based on the properties of Flash Builder project

X

Automated Data synchronization of AIR locale cache

X

X

Flash-based Web reporter

v4

Cost of production deployment

License type and cost

LGPL v3,

Free

MIT,

Free

Commercial, about $30K per CPU****

*   Farata Systems can develop an NIO based BlazeDS solution on a per-customer basis under a separate consulting agreement. Read and watch performance tests of our high concurrency Jetty/NIO/BlazeDS solution at http://flex.sys-con.com/node/720304


** Currently, Farata Systems is working on a solution for introducing the model-driven development to Clear Toolkit.


*** LCDS offers advanced server-side PDF generation. Clear Toolkit components support PDF generation on the client (WYSIWYG), but does not support working with forms.


**** Adobe doesn’t publish the cost of LCDS ES2 license. The price listed here is taken based on the data shared by current users whose employers allegedly paid (read the comments to the following blog post of Adobe LCDS/BlazeDS Product Manager).


I’ll be demoing Clear Toolkit in action at the Flash and The City conference in May in New York City. If you’ll be in town on May 17, consider attending our hands-on master class on modularization of Flex applications.


Yakov Fain

Unleashing the power of Flex,BlazeDS, and Java applications

First of all, Flex and BlazeDS are open sourced and free, which is important for many IT shops even those from filthy rich Wall Street companies. Typically, an enterprise IT group has a limited budget, and even though a more advanced LiveCycle Data Services component offers you more options and better scalability than BlazeDS, for most of the applications using BlazeDS installed in any Java Servlet container is a very solid way of building RIA that are a lot more superior to those built on plain HTTP let alone SOAP Web Services.

The main power of BlazeDS is its binary AMF protocol that seamlessly serializes strongly typed data between Flex and Java. Just think of the typical use case described below.

A POJO on the server side gets a bunch of Customer.java records (say, ArrayList) from a data source and needs to display them as a grid in a Web Browser. With a regular HTML/JavaScript Web application you’d need to convert the customers’ data into some kind of text representation (losing the data types information of customer data), then GZip the data, send them to the client, and using JavaScript manipulations convert the data into appropriate data types for further processing.

You don’t need to do any of these while sending the data from Java on the server to Flex on the client. The ArrayList of customers gets serialized/deserialized into an ActionScript ArrayCollectoin of strongly typed data transfer objects defined in the class Customer.as.

HTTP batching and streaming is a combination of few technologies with a close resemblance to how car traffic is controlled on some highways. There are dedicated lanes for high-occupancy vehicles (HOV) that move faster during the rush hours. Such HOV lanes can be compared to the
HTTP channels opened for streaming. For example, you can program network communications in such way that one channel allows only two data pushes per second (a guaranteed QoS), while the other channel will try to push all the data, which may cause network congestion, delays, and queuing.

With AMF, the data gets loaded faster than with nonbatched requests/responses. And it plays nicely with the typical infrastructures that use firewalls as it piggybacks on the existing browser HTTP requests.

However, for critical HTML/JavaScript applications a problem remains: there is no QoS provided by HTTP protocol, which may become a showstopper. For example, think of a financial application that sends real-time price quotes to the users. The server keeps sending messages, regardless of the current throughput of the network, which in case of network congestion will be causing problems with queues overruns or lost packages.

Recently released LCDS 3 has introduced features to support reliable messaging and throttling, while BlazeDS won’t have it. This is when opensourceness of Flex and BlazeDS becomes handy, because it allows you to customize communication protocols to perfectly meet all the needs of your application and squeeze out a lot more performance from BlazeDS than it’s advertised by Adobe.

How do you even start customizing network protocols? Even the idea of doing this sounds scary, right? It won’t be, if you’ll attend our Master Class in Brussells, Belgium in March: http://www.eventbrite.com/event/527934065. We are planning to run a couple of more if these events in the USA too. Let me throw in some technical terms now since not everyone can appreciate the quality of the Belgium beer yet.

If you open the server-side configuration file services-config.xml that comes with BlazeDS, you’ll find declarations of several communication channels there, for example:

<channel-definition id="my-amf" class="mx.messaging.channels.AMFChannel">
 <endpoint url="http://{server.name}:{server.port}/{context.root}/messagebroker/amf" class="flex.messaging.endpoints.AMFEndpoint"/>
</channel-definition>

This is an example of configured AMF communication channel. There are three important notions to understand here.

1. AMF operates using messaging under the hood. When you make an RPC call to a remote Java class (a.k.a. destination). Flash Player sends messages to the server, and you can change the way messages are being formed or processed.

2. On the client side (Flex) the ActionScript class a.k.a. channel can be customized, if need be. In the example above this would be the class mx.messaging.channel.AMFChannel.

3. On the server side, there are two Java classes that can be customized: an endpoint (see above flex.messaging.endpoints.AMFEndpoint) and adapter.

Let’s say, you want to ensure that every message header includes a userID that has been authenticated during the logon process, you can do it by customizing the channel and the endpoint classes. This way you won’t need to pass the user ID with every application-specific RPC call.

Two years ago, one of our financial clients was concerned with potential out-of-sequence messages in a trading workflow. Back than it was the application based on LCDS 2.5, which didn’t offer any support in this area. We’ve customized the channel and adapter to provide this functionality. We’ve also implemented throttling to slow down the message pushes in congestion situations. The same things can be implemented with BlazeDS.

Or let’s take another real-world situation when an extra security is required: the client’s workstation has to be automatically logged off and disconnected, if the server didn’t respond during a specified time interval. To put it simple, we need to implement some kinds of heartbeats. Yes, you can customize the AMF protocol so it’ll process heartbeats between the Flex client and Java server.

Didn’t respond to my heartbeat within 20 second? You’re a dead man! The user get’s logged out of the system.

Need better performance with BlazeDS? Introduce a non-blocking I/O.
How about an idea of a reverse RPC call? I mean what I mean. A Java server calls a specified function on the user’s (Flex) application passing whatever arguments are required by the function.

“You may say, I’m a dreamer. But I’m not the only one”, sang John Lennon.

For some reason, most of the RIA developers are into flashy UI as it’s considered to be uber cool. But don’t underestimate the power of the networking protocols in general and of AMF in BlazeDS in particular. At least I know, where the power of Flex and Java EE application is hidden.

Yakov Fain

Using Custom Type Marshallers in BlazeDS

In my previous post I pointed to the BlazeDS classes that need to be replaced in order to prevent ActionScript Number.NaN from turning into Long or Integer zeroes on the MessageBroker side. The recommendation boiled down to re-jaring flex-messaging-core.jar or placing the modified classes somewhere earlier in the application server’s classpath. If neither option is allowed, you may configure your endpoint with the custom type marshaller, like the one below:


        <channel-definition id="my-amf" class="mx.messaging.channels.AMFChannel">
           <endpoint url="http://{server.name}:{server.port}/{context.root}/messagebroker/amf" 
           class="flex.messaging.endpoints.AMFEndpoint">
           </endpoint>
           <properties>    
               <serialization>
                   <type-marshaller>clear.messaging.io.amf.translator.NullkeepingASTranslator</type-marshaller>
               </serialization>
           </properties>    
       </channel-definition>

In BlazeDS 4 you will base your type marshaller on flex.messaging.io.ASTranslator:
public class NullkeepingASTranslator extends
    flex.messaging.io.amf.translator.ASTranslator
{
    private static final NumberDecoder numberDecoder = new NumberDecoder();  
    public Object convert(Object source, Class desiredClass)
    {
      if ( DecoderFactory.isNumber(desiredClass)){
        return numberDecoder.decodeObject(source, desiredClass);
      }else{
        return super.convert(source, desiredClass);
      }
    }
}

This route does not require neither server-level deployment nor modification of the flex-messaging-core.jar.

I’d like to use this opportunity and invite Flex developers living in Europe to attend our Advanced Flex Master Class in Brussels, Belgium on March 1 and 2, 2010.

Victor Rasputnis

Prevent Flex numeric nulls from turning to zeros in BlazeDS

This question we get on almost every new client project: “We’re struggling with handling of null values for numeric data types in Flex/Java projects. Every time there’s an update, we end up replacing the original nulls with zeros when the user didn’t actually change that value.  Have you guys come up with a silver bullet for handling numeric nulls?”

Consider a Java method with a Double parameter. You pass uninitialized ActionScript Number, that is, Number.NaN. What will BlazeDS deserialize (unmarshal)? Double.NaN. At this point your Java code may use something like (value==Double.NaN)?null:value, capitalizing on the fact that information about special value of NaN had been delivered from your client code to your server code. Now, let’s assume you change the signature of the Java method to accept Long instead of Double. You pass NaN and you get … 0! The same happens with marshaling ActionScript object that carries Number.NaN properties: they turn into 0, if, god forbid, their Java counterparties are declared as Long or Integer.

The reason is that while Java has Double.NaN it does not support either Long.NaN or Integer.NaN. Looking at the following snippet of code you can see how differently Double and Long variables get treated by Java:


     Double dbl = new Double(Double.NaN); // We emulate incoming numeric null
     System.out.println(dbl); //prints NaN, cause dbl "knows" it came from null
     long l = new Long(dbl.longValue(new Double(Double.NaN)));
     System.out.println(l); // Oops, prints 0!

Unfortunately, native BlazeDS flex.messaging.io.amf.translator.NumberDecoder falls into this trap. So, what is to be done? Luckily, BlazeDS is an open source product and this class has to be slightly modified.

Figure 1 illustrates the changes required to protect null-ability of your Long, Integer, etc values, except Double (we explain what to do with Double-s a bit later):

Modified NumberDecoder class  under Deltawalker

Figure 1. Modified NumberDecoder. Farata modification is on the left, canonical BlazeDS class is on the right.

Now, after you make the changes and compile the class against the rest of the flex-messaging-*** jars you can re-jar your own flex-messaging-core.jar.
Better yer, place this class in the common server folder so that it positively affects classpath of all applications on the server.
From now on, Number.NaN will come as Long null, or Integer null – whatever you decide on the Java side.

It this sounds like to big of a deal to you, keep using Double values and convert Double.NaN to null yourself, when appropriate.


Finally, if you would also like to see Double.NaN automatically converted to null, you will have to substitute one more BlazeDS class – flex.messaging.io.amf.translator.NativeDecoder. Explanation: it’s just so happens that BlazeDS marshalling ignores the NumberDecoder when the source (Number, aka Double) and target (Double) types are the same. Here we come and force BlazeDS to use NumberDecoder with numbers no matter what:

    public class NativeDecoder extends ActionScriptDecoder
{
    public Object decodeObject(Object shell, Object encodedObject, Class desiredClass)
    {
       if ( DecoderFactory.isNumber(desiredClass)){
         NumberDecoder numberDecoder = new NumberDecoder();
            return numberDecoder.decodeObject(encodedObject, desiredClass);
       } else
         return encodedObject;      // the sole original BlazeDS line
    }
}

Source code:
NumberDecoder.java modified by Farata
NativeDecoder.java modified by Farata

I’d like to use this opportunity and invite Flex developers living in Europe to attend our Advanced Flex Master Class in Brussels, Belgium on March 1 and 2, 2010.

Victor Rasputnis

Farata Systems offers enterprise support for BlazeDS

Recently, Adobe decided to stop offering enterprise support for BlazeDS. Here’s an extract from BlazeDS FAQ http://bit.ly/17uzhn:

Does Adobe provide enterprise support for BlazeDS?
We have seen tremendous adoption growth with BlazeDS. However, feedback suggests that the support offerings did not meet the needs of our customers. Therefore, we are no longer offering subscription support for BlazeDS. Instead, customers who require maintenance and support can purchase LiveCycle Data Services ES2. Current customers under a valid support subscription of BlazeDS will have the option to trade up to LiveCycle Data Services ES2 when their maintenance and support agreement comes to an end.”

Over the last two years, Farata Systems was offering various solutions based on BlazeDS often enhancing and extending capabilities of BlazeDS. We are very familiar with the source code of BlazeDS and our Flex and Java experts can support all the needs of your organization around BlazeDS. Support options include all range of services starting from training and first level support to bug fixing and feature enhancements.

Your organization can provide the first level support for the users of the application built with BlazeDS, and Farata Systems takes care of the second level technical support.

Farata Systems can offer your organization the following services:
– a dedicated personnel – 24×7 with limited number of issues/contacts at your organization
– Prepaid blocks of time in 40-hour increments for access to out Flex networking specialists on priority basis
– Customization of the BlazeDS communication protocols if need be
– Increasing of the performance and scalability of BlazeDS-based applications, for an example,
read the following article
– Guaranteed support for 1 year based on product development, with fixed support price thereafter

For more details please fill out the Contact Us form at http://www.faratasystems.com.

Sorry, I’m not a modest person, but at least I’m honest

Today we’ve finally submitted chapter 6 of the book on Enterprise development with Flex to O’Reilly. This one was about advanced techniques of using BlaseDS in communications between Flex and Java.  At this point you’d expect something like, “It’s coming out nicely”.   Sorry guys, I’m not a modest person. But I’m honest.

Here me out: this chapter 6 (66 pages) on advanced  techniques of Flex/Java communications using open source BlazeDS is a gem. This chapter alone is worth buying the book.  Server side push over AMF, reverse side RPC, automatic data synchronization…

I have the best co-authors. Ever. They’re just amazing.  Yes, we fight with each other. We don’t agree. We are not politically correct. We use the f-word when discuss enterprise architecture. We want to find the best possible solution for our customers. We publish thought provoking articles (some people call them controversial, but they are freaking wrong).  But guess what, we’ve been there.  And I’m not talking about sales presentations trying to convince you that Flex/Java does your body good.    “Take a look… it’s just 20 lines of code and we populated the data grid with XML coming from the server”. It’s so sweet….

I’m talking about the real stuff that Wall Street is dealing with day in and day out.  OK. Forget about Wall Street. They are still out of style. Let’s talk about the calls like this one, “We are going live in two months. Can you please take a look at our application it doesn’t perform that great.”

Oh, really….It doesn’t perform well? Don’t kid yourself. It’s dead in the water. I know, I know. You’ve outsourced the development. It seemed so easy to drag and drop Flex components… You didn’t get a chance to schedule stress tests yet? How many? Ten thousand users will play online roulette…? We’ll do our best.

I don’t know why O’Reilly decided  to sell this book for stinking fifty bucks.  We don’t have a say in pricing. But it should cost  a lot more than that.
Sorry, I’m not a modest person, but at least I’m honest.

Yakov

Data Synchronization with BlazeDS: Handling AUTOINCREMENT

Upcoming release of the ClearDataBuilder supports AUTOINCREMENTed property in the DataCollection items populated from databases based on autogenerated values like MSSqlServer/ Sybase identity, or Oracle’s sequence, and so forth. All you need to do is add identity parameter to the CDB annotation
[quickcode:noclick] /**
* @daoflex:sql
* sql=select * from employee
* transferType=EmployeeDTO[]
* keyColumns=id
* identity=id
* updateTable=employee
*/

public abstract List getEmployees();[/quickcode]
and allow server changes to reflect back on the DataCollection:
[quickcode:noclick]dataCollection.roundTripSync = true; [/quickcode]


Sample Use Case

Imagine a MSSqlServer table “employee”, with IDENTITY column named “id”. Here is the abstract Java class you would need to write:

package com.farata.test;
import java.util.List;
/**
 * @daoflex:webservice
 *   pool=jdbc/test
 */
public abstract class Employee
{
    /**
    * @daoflex:sql
    *  sql=select * from employee
    *  transferType=EmployeeDTO[]
    *  keyColumns=id
    *  identity=id
    *  updateTable=employee
    */

    public abstract List getEmployees();
}

A Clean CDB build, as usual, will generate concrete implementation of the Assembler, already registered for Flex remoting, ActionScript DTO classes matching the Java counterparties and so forth.

Importantly, the specifics of the identity annotation will force CDB to enquire the value of the autogenerated id column along with the execution of the executeUpdate() and send the modified record back to the Flex client.


Two-Way Syncronization: DataCollection – BlazeDS Assembler

You have to allow the echo of the server-side changes back to the client. You have two options.

  • dataCollection.roundTripSync=true; – to allow Flex process the immediate result of “your own” dataCollection.sync() call
  • dataCollection.autoSyncEnabled=true; – to allow Flex consume server-born asyncronous messages with changes inflicted by other clients. This option requires design-time autoSyncEnabled=true CDB annotation as well.

    Here is the explanation. During the sync() operation changes originated in the DataCollection are remoted to method(s) of a server Assembler as Array of com.farata.remoting.ChangeObject elements. All of these methods are also returning the Array of changes, including, if any, changes originated by the server. The value of the roundTripSync determines whether these changes effect DataCollection when the synchronization is complete. Default value is false


    Pluggable Identity Factory

    No two databases are born equal. The default setting of the CDB is to handle identity compliant with MSSqlServer, i.e. to use SELECT SCOPE_IDENTITY() as the cleanest possible computation of the identity. If you are running Sybase, you would have to modify the default daoflex.identity.factory in the daoflex-build/daoflex-build-custom.properties:

    daoflex.identity.factory=com.farata.daoflex.SybaseIdentityFactory
    

    It gets worse if you are an Oracle sequence guy. Plugging a foo.bar.OracleIdentityFactory class that has to implement com.farata.daoflex.IIdentityFactory interface is not any different from the Sybase, but CDB does not know upfront which sequence to use. So roll up your sleeves and create something like following:
    package foo.bar;
    
    import java.sql.Connection;
    import java.sql.PreparedStatement;
    import java.sql.ResultSet;
    import java.util.Map;
    
    import com.farata.daoflex.DAOException;
    import com.farata.daoflex.IIdentityFactory;
    
    public class OracleIdentityFactory implements IIdentityFactory {
      public long getIdentity(Map<String, Object> properties) {
        long identity = 0;
        PreparedStatement stmt = null;
        ResultSet rs = null;
        try {
        
          Connection conn = (Connection) properties.get(CONNECTION);
          String table = (String) properties.get(TABLE);
          String sequenceName="UNKNOWN_SEQUENCE";  
          // Your custom logic to determine the sequence give the table goes here    
          if (table==table) 
               sequenceName = "MY_SEQUENCE";      
          stmt = conn.prepareStatement("SELECT " + sequenceName + ".NEXTVAL AS identity FROM DUAL");
          rs = stmt.executeQuery();
          while( rs.next() ) {
            identity = rs.getLong("identity");
          }
          return identity;
        } catch (Throwable te) {
          te.printStackTrace();
          throw new DAOException("Failed creating identity", te);
        }
        finally {
          try {rs.close(); rs = null;} catch (Exception e){}
          try {stmt.close(); stmt = null;} catch (Exception e){}
        }
      }
    }
    

    Victor Rasputnis