In my last post, I talked about Service-Oriented User Interfaces (or SOUIs). In this post, I want to get more specific about what that means from a development perspective. In practical terms, a SOUI is nothing more than a composition of Service-Oriented Components.
A Service-Oriented Component is a component whose behavior and visual appearance is driven by a message and optionally some data in that message. In Appcelerator, we turn standard HTML elements into Service-Oriented Components. Let’s look at some examples:
Example 1: Progress indicator
1
2
3
4
| <div on="r:login.request then show or r:login.response then hide"
style="display:none">
<img src="images/progress.gif"/> Processing Login....
</div> |
In Example 1, the display of a standard HTML <div> is controlled by two separate messages. The login.request message triggers the <div> to show and the login.response message will trigger the <div> to hide.
Note: Appcelerator Client messages are always prefixed with either an l: or an r:. The former tells Appcelerator that the message should only be sent locally (i.e., within the browser). The latter will result in the message being sent both locally and to a service.
Example 2: Submitting a form
1
2
3
4
5
6
| <div>Username:</div>
<input type="text" id="username" fieldset="login"/>
<div>Password:</div>
<input type="password" id="password" fieldset="login"/>
<input type="button" value="Login" fieldset="login"
on="click then r:login.request"/> |
In Example 2, when the user clicks the “Login” button, a request will be sent to a service that subscribes to the login.request message. The message’s data payload will contain two name/value pairs: ‘username’ with the value of the username input field and ‘password’ with the value of the password input field.
These two simple examples demonstrate both the power and simplicity of Service-Oriented Components. In Appcelerator, Service-Oriented Components are possible because of Appcelerator’s integrated Message-Oriented Architecture. This architecture binds user interface elements to services via a lightweight message contract. Appcelerator Message Contracts have two parts:
- message name (e.g., “login.request”)
- message data payload (i.e., one or more name/value pairs)
In Example 2, the “Login” form and the “Login” service share a message-based contract. This contract has a message name: login.request and two name/value pairs: username and password.
Service-Oriented Components can also take action based on the combination of a message and its data payload. Let’s look at some examples:
Example 3: Show an element based on message data
1
2
3
4
| <div on="r:user.registration.response[success=true] then show"
style="display:none">
Your registration was successful as far as you know...
</div> |
In Example 3, the registration message will only be shown if the r:user.registration.response message contains the name/value pair ’success’=true.
Example 4: Set styles and element values based on message data
1
2
3
4
| <div on="r:login.response[gender=male] then set[border='1px solid blue']
else set[border='1px solid pink']" style="display:none" >
Welcome back, <span on="r:login.response then value[name]"></span>
</div> |
In Example 4, several user interface actions occur based on the message login.response and its data payload:
- The border of the <div> is set to blue if ‘gender’ is ‘male’, otherwise its set to pink
- The value of the <span> is set to the user’s name in order to complete the “welcome” message
These examples provide just a glimpse of the power of Service-Oriented Components. I’ve been developing applications this way for over a year, and I believe the benefits are enormous. Here are just a few:
- You get more functionality with significantly less code, or as we like to say: “More App. Less Code.”
- You can easily Ajax and DHTML-enable standard HTML elements without writing any Javascript
- You can create mock service handlers on the client - the result is a fully functional client prototype that is 100% resusable
- You get a very clean separation between the client and its services.
Now that I’ve set a new world record for using the phrase “Service-Oriented Component” in a blog post, my work here is done, plus you need to get back to work - your boss is standing right behind you.
Popularity: 8% [?]
Model-View-Controller (MVC) was the exclusive design pattern for Web 1.0. These Web 1.0 MVC-based frameworks still dominate the world of web development, but that is about to change. Here’s my hypothesis:
MVC-based frameworks are simply unable by design to take advantage of the full power of Ajax and DHTML. Therefore, we must take a step back and a look at the problem of web development with a fresh perspective.
Note: going forward I will refer to “Web 1.0 MVC-based frameworks” as “Ralph” since the former is such a mouthful.
Ajax4Ralph
Many of the Ralphs have added support for Ajax (e.g., JBoss Seam via JSF/Ajax4JSF and Ruby on Rails). Let’s take a look at an actual Ajax request message from the JBoss Seam Hotel Booking Application:
Ajax-flavored Alphabet Soup
This is Ajax on Ralph – a clear illustration that Ralph is not designed to play nice with Ajax. To work with Ajax, Ralph must do unnatural and awkward things and the result is what you see above. There is another problem with Ajax and Ralph. Ralph forces an almost airtight coupling between the user interface and the server, whereas Ajax enables a near-100% decoupling of the user interface and the server. Viewed in this light, you can see that Ralph and Ajax are at odds, so it should not be surprising that when combined the result is a train wreck.
DHTML4Ralph
DHTML enables you to create highly dynamic user interfaces. You can hide or show an element, change CSS properties on the fly, drag-and-drop elements, and much more. How does Ralph help you with DHTML? To date, Ralph gives you two ways to incorporate DHTML:
- You can handwrite Javascript
- You can integrate with a third-party DHTML-toolkit like Dojo.
Both solutions can help you build dynamic applications, but neither is ideal or integrated. Handwriting Javascript is a nightmare. I know because I’ve done it. Over a year ago, I wrote a nice login/signup page; it was highly dynamic, and it looked and performed quite well. The problem was it required 1400 lines of code - 1000 of which were Javascript. It was clear that this approach was deeply flawed and had absolutely no future.
Next, I tried using toolkits like Dojo. This approach required me to write less Javascript, but integration was not straightforward. These toolkits are also hard to customize and they still require you to write a fair amount of Javascript. The biggest problem is that they are not integrated; they are “bolt-ons”.
At best, Ralph has “bolt-on” support for both Ajax and DHTML. You can certainly create next-generation applications using Ralph, but you can also eat nails; neither is a fruitful experience. The problem is simple: Ralph was designed in a time before Ajax and DHTML. In his defense, Ralph has tried hard to support these technologies, but the result is awkward and difficult to use. Good engineers know instinctively when it’s time to take a step back from a problem and look at it with a fresh perspective. Now is that time.
With that in mind, it’s time for my next hypothesis:
Ajax and DHTML are highly complementary technologies - when combined they enable the creation of web applications that can surpass the capabilities of today’s desktop applications. As a result, a next-generation Web SDK is needed - one that seamlessly integrates Ajax and DHTML.
Introducing the SOUI (like the pig call: soo-wee!)
SOUI stands for Service-Oriented User Interface. The foundation of a SOUI is a message-based architecture - meaning everything in the user interface is controlled via lightweight messages. Think about being able to control both the look of the user interface and the interaction with services using a single messaging paradigm. With one message, you can hide 3 HTML elements, show another, and send a service request – pretty cool. The SOUI also provides an abstraction layer that seamlessly integrates DHTML and Ajax - giving developers the benefits of Ajax and DHTML without having to write any Javascript. The result is a powerful, streamlined, and highly flexible way of building dynamic user interfaces, but enough talk, let’s look at some code:
1
2
3
4
5
| <!-- SHOW AN INDICATOR ON SAVE, HIDE ON RESPONSE -->
<img src="http://www.example.com/indicator.gif"
on="r:user.save.request or r:user.save.response then hide"/>
<!-- SEND A REMOTE USER SAVE REQUEST -->
<input on="click then r:user.save.request" type="button" /> |
In the example above, clicking the button generates a message, which results in two actions: an Ajax request to a service and a DHTML action that shows a spinning progress image. When the Ajax response is returned, the image is hidden using another DHTML action. That’s SOO-WEE! – simple, yet powerful.
The message-driven nature of a SOUI also provides some other significant benefits:
- You can create client-only prototypes that are fully functional since they can use local mock message handlers. The SOUI does not know the difference between using a mock message handler and using a service.
- These prototypes are 100% re-usable – just swap out the mock message handlers for the actual services without changing any SOUI code.
- You create a simple message-based contract between the SOUI and its services. The result is a near-complete decoupling of the client and server; they are linked only by a lightweight message contract.
- You can change your server programming language without changing a single line of SOUI code.
SOA for Web Applications
A SOUI-based client opens the door for some interesting things on the server. Since SOUIs talk to services using lightweight messages, services can now be written in any programming language. In other words, a SOUI is programming language-agnostic. It can talk to services in Java, Ruby, PHP, .NET or any other programming language you can dream up. It can also simultaneously access services in different programming languages. These powerful capabilities are enabled by the lightweight message contract between the SOUI and the service. The only knowledge shared between the SOUI and the service is this contract. Let’s take a look at one of these messages. The message below is how a SOUI would request data from a service providing the same capabilities as the JBoss’ Seam Hotel Booking example provided earlier:
1
2
3
4
5
| <request version="1.0" idle="403">
<message requestid="2" type="hotel.search.request" datatype="JSON">
<![CDATA[{"searchKey":"Atl"}]]>
</message>
</request> |
Within this message lies the Message Request Contract. This contract has two parts: the message type and the message data. The message type in this case is hotel.search.request. The message data for this contract is searchKey. So we have a service that responds to all requests for hotel.search.request and it requires an value for searchKey to do its job – simple, yet powerful. Let me hear you squeal – SOO-WEE!
This lightweight message contract should also greatly simplify service development. There is no longer a need for the heavyweight infrastructure required by Ralph. In Java, I should now be able to create a plain Java object (POJO) and add a single annotation that instantly makes it a service that can be consumed by a SOUI. Here’s an example Java service:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
| public class HotelService
{
@InjectBean
HotelDAO hotelDAO;
@Service(request=”hotel.search.request,response=”hotel.search.response”)
public hotelSearchRequest(Message request, Message response)
{
// get request data
String searchKey = request.getData().getString(“searchKey”);
// perform search
List<hotel> hotels = hotelDAO.findByName(searchKey);
// send response
response.getData().put(“hotels”,hotels);
}
} |
As you can see, the SOUI unleashes the full power of an SOA-based architecture for web applications. Web service developers can now focus solely on developing a set of reusable data services in the programming language of their choice, and they no longer have to co-mingle service logic with presentation code. And user interface designers are now free to rapidly create highly dynamic user interfaces with less code and without the constraints of Ralph’s forced-coupling of client and server technologies.
Now What?
My business partner Jeff Haynie and I went through this thinking over a year ago. We were frustrated by the state of web development platforms. Our conclusion was that it was time to take a step back and design a solution that would unleash the full power of Ajax and DHTML and solve the coupling problem created by Ralph. The result is Appcelerator. We’ve been building applications with Appcelerator for over a year and the result has been phenomenal. In short we’ve been able to build highly dynamic applications with significantly less code in a fraction of the time - hence our tagline: More App Less Code.
This is just the beginning of the what’s to come. The implications of an Applcelerator-type platform do not stop with development. The effects are far-reaching, incredibly exciting and will change how people build, deploy and manage web-based applications and services.
Popularity: 23% [?]