Archive

Archive for February, 2008

Effectively Implementing Appcelerator RIAs and Services

February 26th, 2008 Andrew Zuercher 2 comments

Purpose

If you are venturing to implement a Rich Internet Application (RIA) with Appcelerator, then there are features about the framework that I’m really geared up about that help you implement your solution effectively. When used together these items enable the agile creation of solutions in a shorter time that integrate nicely with services in an existing architecture and provide a richer user experience for clients.

Achieving Re-use

There are a bunch of ways to do this, personally I leverage app:content files judiciously. You can provide args in the definition of your content files so that you can use the same content file over again. Some things to keep in mind:

  • reference the args as #{argname} in your element ids, any variables, and make sure that functions you call take this into account (possibly make them stateless)
  • the order in which the content file is loaded to make sure that listeners are properly setup to respond to messages

here is an example app:content reference

1
2
3
<app:content lazy="false" on="mainstate[person] then show else hide" 
  args="{'prefix':'person'}">
</app:content>

here is the content.html file

1
2
<div id="#{prefix}header" ...
</div>

I know that this may be abstract, but the point is that you can use the arg “prefix” to reuse the file and provide alternative behavior based on it.

Mocking Services

You can mock out server side services extremely easily with the framework. This is extremely useful whether your goal is:

  • Visual Use Cases: implementing a prototype that results in 100% useable application code
  • Working offline: no need to run a web server at all, you can directly run off of a simple file

Once you have this in place, you have a well defined contract in place which makes knocking out the service implementation a snap.

No restart

If you are just working on your application (no service work), you can directly make changes to your application without requiring rebuilding and redeploying your application. In java I typically work directly in my tomcat deploy directory and have an ant task to pull the web files into my workspace. With our next version of the framework coming out, this will be even easier with our support for Jetty coming and the Ruby based command line tool. In the meantime, the following is useful in your java project:

1
ant pullweb

Make sure that you have your deploy.dir setup in your $HOME/.ant.properties for example:

1
deploy.dir=/Applications/apache-tomcat-6.0.14/webapps

With our Ruby implementation for example, this is even easier (running webbrick directly in your workspace).

Great Support for Model Objects

I’ve touched a bit on this in a previous post on JSON serialization with Appcelerator java services. To summarize the framework enables

  • Hibernate persistence: ModelObjects can easily be used with our Hibernate integration
  • JSON serialization: Serializing and deserialing complex objects is a snap

Slick support for forms

In case you haven’t looked, you dont need to include a form tag anywhere in the application: simply add a fieldset attribute to your input elements and put something like this

1
2
3
4
<input name="age" fieldset="save_person" type="text"/>
<input name="name" fieldset="save_person" type="text"/>
<input value="Create Person" fieldset="save_person"/>
  on="click then r:create.person.request" type="button"/>

This will create a message of type r:create.person.request with the payload being all your input elements with fieldset of “save_person” ex:

1
{'name':'jim','age':'35'}

To me, this is very eloquent solution to leveraging form input elements with a messaging architecture.

Easy to use UI widgets

I love some of the widgets that are at your fingertips. Some of the ones that i use the most

  • app:panel: slick styling
  • app:datatable: great way to show rows of data
  • app:chart: fantastic visual effects to bring life to data

All these widgets have a very terse usage that is very intuitive. For example, using this set, I was able to knock out a realtime dashboard application in 3 evenings.

Service Platform Options

Pitching the right framework is something that varies from project to project. For example, possibly your client wants to leverage an existing java infrastructure and is sold on its robustness for scaling enterprise applications, while on the other side possibly you want to take advantage of using a Rails controller and ORM/Active Record implementation for rapid development. On the same level you also have the option for implementing services to customers that deliver in a .Net solution architecture. Many other platforms also exist (python, PHP) enabling the opportunity to plug into those services as well.

The app:get non-visual widget also makes pre-existing services accessible as well and since Messaging is at the heart of the implementation, plugging into an ESB or pure MOM framework is perfectly setup as well.

Wrap Up

In this article 7 key tips have been covered

  • re-use
  • mock services
  • no restart
  • model objects
  • messaging & forms
  • UI widgets
  • platform options

Although there are more items that have not been covered here, these are the ones that appeal personally to me and have noticed a huge gain in doing much more with less effort.

Technorati Tags: , ,

Categories: announcements Tags: , ,

Debugging Appcelerator Applications

February 21st, 2008 Andrew Zuercher No comments

Purpose

The ability to debug applications is critical when things go sideways on you. I understand that for some of the developers out there learning a new framework can be challenging. Appcelerator provides developers with the tool-set to drastically reduce the amount of javascript code that they need to write and to be honest I think that the more you use the framework, the less you will need to debug applications as you familiarize yourself with the syntax.

Alerts

Prior to logging, alerts were the best way to display state during execution (showing you how old school I’ve been). Nonetheless, sometimes this is just easier since it blocks execution until you confirm. When you do this, you may want want to display objects. Lets take for example the following

1
alert(myobject);

You make get an alert that shows:

alert_object.png

Well that isn’t very useful. If you want a nice string representation, use the following

1
alert(Object.toJSON(myobject));

Now you’ll get a nice JSON representation.

alert_json.png

Logging

Safari and Firefox both provide you with the ability to view logging in the console. For firefox, you need to install firebug. If you are a safari user, you can use webkit (from the Debug menu, click “Show Javascript Console”). Both of which make available a console that displays log statements.

In firefox you can do the following in javascript

1
console.log("wassup");

I suggest however that you dont do that! Instead make use of the abstracted Logger

1
Logger.info("wassup");

This will not only show up in Firefox, but also in Safari’s console.

wassup.png

On another note, you can use the debug=1 parameter in your URL and you will see a ton of appcelerator messages (ex: http:localhos:8080/myapp?debug=1). I will caution you that it will almost look like spam given the amount of detail that is logged, but nonetheless its there if you want it.

You can also expand the Get and Post statements in firefox which will let you know what you have sent in your request and the JSON result that was returned from the server.

ajaxlog.png

In-line Debugging

Lets say that you have an error in your app:script. Well in Firefox, you can take a look at the console and that will give you some pretty good feedback, however its going to be some cryptic text and you can’t step through it. You have 2 options that will enable you to step through the code:

  • can make a call to a javascript function from your app:script (I normally define a project specific javascript file and put my functions in it)
  • define a $MQL in your javascript file – app:script goes away

Here is scenario 1:

1
2
3
<app:script on="r:someevent.response then execute">
  Myapp.dosomething(this.data);
</app:script>

and the corresponding javascript

1
2
3
4
5
Myapp = Class.create();
Myapp.dosomething = function(data)
{
  //code here
}

For scenario 2: alternatively you could just define in your javascript file

1
2
3
4
$MQL('r:someevent.response',function(type,msg,datatype,from)
{
	//code here
});

The downside of this is that your implementation is not colocated in a single html file, but the upside is that you can debug it. Note that if you are not using content files, then you could alternatively define the above in a script element instead (a little cleaner), however if its a large app, then you really will want to decompose your app and use content files.

IE Specific Debugging

To be honest I’m not a huge IE fan, but it makes up an install base of 80% of the market. Chances are that pretty much everyone out there is using IE if you are building an application that appeals to the general public. To this end, Microsoft has made the .Net Developer Studio available for debugging your applications. The steps are pretty simple:

  • install .Net Studio and create a project
  • add your javascript files to your project
  • start IE with your app’s url
  • in Visual studio, select debug process and select your iexplorer.exe (sometimes it wont attach, but just keep trying and you should get there eventually)

For understanding styling, I suggest downloading the Internet Explorer Developer Toolbar. This will allow you to inspect individual elements (using the hover) and then setting styling attributes on your elements. This is much better than changing your html and reloading your page, especially for large applications.

Firefox (Firebug) Specific debugging

As with IE, you can use the firefox plugin to step through your code.

  • load your app
  • open firebug
  • click script and select the html or javascript file and set your breakpoints

As with IE, using the Inspect module in firebug is very useful for styling your application.

Wrap Up

In this article we covered a bunch of ways that you can get down to the details in your application

  • alerts (and displaying objects as strings)
  • logging (appcelerator debug mode, custom log statements, ajax payloads)
  • in line javascript debugging and styling

For many this may be an obvious repeat of the mechanisms that they currently use as web developers, but hopefully it will uncover some of the tactics that are used.

-andrew

this blog is cross posted at:
http://zuerchtech.com/2008/2/21/debugging-appcelerator-applications

Technorati Tags: , ,

Categories: announcements Tags: , ,

Performance Tuning Appcelerator Applications

February 20th, 2008 Andrew Zuercher No comments

Purpose

Once you have developed a functional application and are priming for a roll-out, it will be in your interest to tune your application and identify those touch-points which are candidates for tuning. I’ve preferred taking a quantitative approach to performance tuning so that you can compare metrics before and afterwards to identify improvement from a measurable perspective. To this end, it is possible to record statistics both client and server side (currently only for java services). Sometimes the culprit may be server side or client side and determining the area where performance bottlenecks exist is important which is why taking on a triangulation approach is important.

Client Side

Currently in the client, you can invoke the Appcelerator.Util.Performance component. To enable it, simply include logStats=1 in your url, for example: http://localhost:8080/myapp?logStats=1. The performance component by design will have no impact on your application unless you include this parameter. By default, the servicebroker will calculate the statistics for handling all message types both local and remote. The statistics will include the following:

  • last – the last recorded time
  • mean
  • hits – aka count
  • min
  • max
  • total – total time overall

These statistics will be logged to the console (available in Firefox with Firebug and in Safari with Webkit).

logging output

However, you do not need to have logging available to inspect the statistics (please see the section “Viewing Client Side statistics” below). In addition the component also allows for resetting all statistics to restart your recording.

Capturing your own statistics

If for some reason you want to capture statistics at a finer level, you can easily to this in javascript:

1
2
3
var stat = Appcelerator.Util.Performance.createStat();
//do some work
Appcelerator.Util.Performance.endStat(stat,"mystat","mycategory");

In this example we create a statistic called “mystat” that will be included in a category of “mycategory”. This is useful for filtering through your stats as well as being able to compare statistics side by side. For example, the service broker will automatically record the following categories:

  • remote
  • local

Viewing Client Side statistics

You may want to include the following content file in your application and make it visible when the logStats=1 parameter is included.

performance screenshot

Here is the content source itself
clientperformance.html

Tuning Considerations

As you develop larger applications, it may be useful to consider the following tips:

  • use lazy=true for app:content files. this will help to delay long initial load times for your applications
  • if you do not lazily load your content files, consider postponing app:message invocations until they are needed
  • consider using CSS selectors in the implementation of your app:iterator rather than re-firing messages for logic
  • leverage the app:datacache to reduce the number of outgoing messages
  • make use of pagination if rendering large datasets – the app:datatable allows for client side pagination for example

Wrap Up

We covered in this article

  • how you can capture statistics for client side applications
  • some performance tips in regards to client applications

In a later article we will identify how you can take this a step further to capture statistics on the server side as well with java services.This article has been cross posted on

  • http://zuerchtech.com/2008/2/20/performance-tuning-appcelerator-applications
  • Technorati Tags: , ,

    JSON serialization with appcelerator java services

    February 8th, 2008 Andrew Zuercher No comments

    Using Model Objects

    The issue of serializing/transforming model objects is not new, heck I’ve been doing this for quite some time:

    • rmi (ejb/corba)
    • xml (jms, soap, etc..)
    • json

    JSON is not the only way to serialize objects for web2.0 applications, but its the most abundant and heavily used throughout our framework. Doing this is actually really easy to do with appcelerator IModelObejects. Our IModelObjects can easily be used along with hibernate for persistance, but lets leave that for later for now. When you define your Model classes, there are some very simple things to keep in mind:

    • annotate your attributes with @MessageAttr
    • have your class implement IModelObject

    Here is a simple example:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    
    public class User implements IModelObject, Serializable {
      private static final long serialVersionUID = 1L;
     
      @MessageAttr
      public String name;
     
      public void setUsername(String username) {
        this.username = username;
      }
     
     public void setPassword(String password) {
       this.password = password;
      }
     
      ...
    }

    Unit test it

    Now to test the rendering of our object to JSON with a simple junit test…. As you can see, we leverage the Appcelerator framework to serialize our objects to JSON

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    
    public class ForumTest extends TestCase { 
     
    public void testSimple() {
      User user = createUser();
      Message message = new Message();
      JSONMessageDataObject data = new JSONMessageDataObject();
      message.setData(data);
      message.getData().put("user", user);
      message.getData().put("count", 1);
      String messagestr = data.toDataString();
      assertEquals(messagestr,"\"user\":{\"password\":\"pwd\",\"threads\":0,\"fullName\"
      :\"antewew\",\"username\":\"azuercher\",\"state\":\"mystate\",\"email\":\"email\",
      \"posts\":0,\"id\":0},\"count\":1}");
    }
     
    private User createUser() {
      User user = new User();
      user.setEmail("email");
      user.setFullName("ante wew");
      user.setId(new Long(0));
      user.setPassword("pwd");
      user.setPosts(new Long(0));
      user.setState("mystate");
      user.setThreads(new Long(0));
      user.setUsername("azuercher");
      return user;
    }
     
    }

    Dealing with recursion

    Whats always a bit of a tangle is understanding how to deal with the recursive/circular relationship.
    If you take a look at JSONObject you will see 2 overridden methods for createBean

    1
    2
    
    public static JSONObject createBean(IModelObject object,MessageAttr parentAtt, String context,String[] parentSuppres,int level, int maxlevels)
    public static JSONObject createBean(IModelObject object)

    The latter is obviously a bit more simple, but the former is where the power is. In the MessageAttr annotation, you can provide the suppress attribute which is a comma separated list of aggregates (using bean.name notation to not serialize). This is used for attributes in your IModelObject implementation where the association is with another IModelObject. The following model is for a forum object model where the following aggregate hierarchy exists:

    1
    2
    3
    
    * Forum
    ** ForumThread
    *** Post

    In the snippet below, I’ve omitted the getter/setter methods for the aggregates for simplicity.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    
    public class User implements IModelObject, Serializable {
      @MessageAttr (suppress="user,thread.lastPost")
      public Post lastPost;
    }
     
    public class Post implements IModelObject, Serializable {
      @MessageAttr(suppress="lastPost,forum.lastPost")
      public Forumthread thread;
     
      @MessageAttr (suppress="lastPost")
      public User user;
    }
     
    public class Forumthread implements IModelObject, Serializable {
      @MessageAttr (suppress="lastPost")
      public Forum forum;
     
      @MessageAttr (suppress="thread,user.lastPost")
      public Post lastPost;
    }
     
    public class Forum implements IModelObject, Serializable {
      @MessageAttr (suppress="thread.forum,thread.lastPost,user.lastPost")
      public Post lastPost;
     
    }

    Rolling your own serialization

    Assuming you know what your JSON string is going to look like, you can use our RawMessageDataList and RawMessageDataObject to serialze your objects. This is pretty useful if you already are rendering JSON in an existing framework and don’t want to have to transform to and back again. The snippet below shows with static strings just so that you get the idea:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    
    IMessageDataList people = new RawMessageDataList(
    "[{'name':'joe','age':22},{'name':'jane','age':33}]");
     
    IMessageDataList dog = new RawMessageDataObject("{'breed':'doberman','weight':78}");
     
    Message message = new Message();
    message.setData(new JSONMessageDataObject());
    message.getData().put("people", people);
    message.getData().put("dog", dog);

    Using Coarse Grained objects

    This is probably the simplest/prettiest way to implement your services assuming that you aren’t interested in using fine grained classes that are associated with most of today’s persistence frameworks. Here is how you would create a single compound JSON object:

    1
    2
    3
    4
    5
    
    IMessageDataObject dog = MessageUtils.createMessageDataObject();
    obj.put("breed","doberman");
    obj.put("wieght",78);Message message = new Message();
    message.setData(new JSONMessageDataObject());
    message.getData().put("dog", dog);

    and now with a collection:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    
    IMessageDataList&lt;IMessageDataObject&gt; people =
    MessageUtils.createMessageDataObjectList();
     
    IMessageDataObject joe = MessageUtils.createMessageDataObject();
    joe.put("name","joe");
    joe.put("age",22);
     
    IMessageDataObject jane = MessageUtils.createMessageDataObject();
    joe.put("name","jane");
    joe.put("age",33);
     
    people.put(joe);
    people.put(jane);
     
    Message message = new Message();
    message.setData(new JSONMessageDataObject());
    message.getData().put("people", people);

    Summary

    As you can see there are quite a bit of alternatives for you based on what your needs are to accommodate your service implementations. I’ve personally used all of the above as I’ve implemented:

    • Model Objects: using hibernate for persistence
    • Custom Serialization: for integrating with pre-rendered objects (commons-monitoring)
    • Coarse Grained: in implementing a dashboard/event driven solution

    cheers and enjoy,

    -andrew

    cross-posted @ http://zuerchtech.com/2008/2/8/json-serialization-with-appcelerator-java-services

    Technorati Tags: , , ,

    Categories: announcements Tags: , , ,