Tuesday, June 24, 2008

An OpenLaszlo RSS Reader Implementation

In this blog entry, I demonstrate generation of a simple RSS Reader using OpenLaszlo. The world certainly doesn't need another RSS reader, so the purpose of this blog entry is to demonstrate some of the easy-to-use features of OpenLaszlo.

The RSS reader shown in this blog entry will focus on blogs hosted on Blogger (blogspot.com). There are two URLs one can use to access RSS feeds from blogs with the blogspot.com domain. These are listed next with my own blog URL (marxsoftware.blogspot.com) used as the example.

1. http://marxsoftware.blogspot.com/feeds/posts/default?alt=rss (see Blogger Feed URLs for additional details)

2. http://marxsoftware.blogspot.com/rss.xml

This example will use the first type of URL to access blogspot.com-based RSS feeds and display the blog entries titles, URLs, and summaries if available. This simple reader allows the user to enter the main part of the blogspot.com blog name and the remainder of the appropriate RSS URL is constructed automatically. By default, this blog's RSS feed is initially displayed, but it can be changed to any other blog on the blogspot.com domain.

The next three screen snapshots show the OpenLaszlo-based RSS Reader displaying RSS feed information from the blogs http://marxsoftware.blogspot.com/, http://jacksonsoftware.blogspot.com/, and http://mmartinsoftware.blogspot.com/. Click on the screen snapshots shown here to see larger version.

OpenLaszlo-based RSS Reader Showing My Blog RSS Feed




OpenLaszlo-based RSS Reader Showing Bill's RSS Feed




OpenLaszlo-based RSS Reader Showing Michael's RSS Feed




With an idea of how the RSS Reader built on OpenLaszlo works, it is time to turn to the code. I'll first list the entire listing for this OpenLaszlo application and then will focus on some pieces of it.


<canvas title="Blog RSS Reader">
<!-- Dataset bound to blog's RSS feed. -->
<dataset name="blogRssFeed"
request="true"
src="http://marxsoftware.blogspot.com/feeds/posts/default?alt=rss" />

<!-- Alternative RSS Feed URL: http://marxsoftware.blogspot.com/rss.xml -->

<!-- Allow for BlogSpot/Blogger URL input. -->
<window name="urlEntryWindow"
title="Provide BlogSpot/Blogger URL"
width="${parent.width}" height="15%">
<view name="blogUrlSelectorView" width="${parent.width}">
<simplelayout axis="x" spacing="5" />
<statictext name="entryLabel">Enter blog name:</statictext>
<inputtext id="urlInputText"
width="${parent.width*.35-parent.entryLabel.width}" />
<text id="urlDisplayText"
width="${parent.width*0.35-5}"
bgcolor="0xFFFF99">
<handler name="ontext" reference="urlInputText">
/*
this.setText( "http://" + urlInputText.getText()
+ ".blogspot.com/rss.xml");
*/
this.setText( "http://" + urlInputText.getText()
+ ".blogspot.com/feeds/posts/default?alt=rss");
</handler>
</text>
<button>
<font color="0xFF00FF">Process this RSS Feed</font>
<handler name="onclick">
blogRssFeed.setSrc(urlDisplayText.getText());
blogRssFeed.doRequest();
</handler>
</button>
</view>
</window>

<!-- Presentation of blog RSS feeds. -->
<window title="Blog RSS Reader"
y="${parent.urlEntryWindow.height}"
width="100%" height="85%">
<view width="${parent.width}">
<view datapath="blogRssFeed:/rss/channel/item"
width="${parent.width}">
<simplelayout axis="y" spacing="5" />
<view name="feedTitleView" width="${parent.width}">
<simplelayout axis="x" spacing="10" />
<text name="rssFeedTitleLabel"
text="TITLE: "
fontsize="12"
fontstyle="bold"
resize="true"
width="${parent.width*0.1}" />
<text name="rssFeedTitle"
text="$path{'title/text()'}"
fontsize="12"
fontstyle="italic"
resize="true"
width="${parent.width*0.9}" />
</view>
<view name="feedLinkView" width="${parent.width}">
<simplelayout axis="x" spacing="10" />
<text name="rssFeedLinkLabel"
text="URL: "
fontsize="12"
fontstyle="bold"
resize="true"
width="${parent.width*0.1}" />
<richinputtext name="rssFeedLink"
text="$path{'link/text()'}"
fontsize="12"
resize="true"
width="${parent.width*0.9}"
selectable="true">
<handler name="ontext">
htmlLink = new textformat(); // LzTextFormat is deprecated
htmlLink.setAttribute("url", this.getText());
htmlLink.setAttribute("target", "blank");
this.setHTML(htmlLink);
this.setTextFormat(htmlLink);
</handler>
</richinputtext>
</view>
<view name="summaryView" width="${parent.width-10}">
<text name="summaryText"
text="$path{'summary/text()'}"
fontsize="10"
resize="true"
width="${parent.width}"
multiline="true"
x="${parent.x+5}" />
</view>
</view>
<simplelayout axis="y" spacing="25" />
</view>
<!-- Laszlo scrollbar is along y-axis by default. -->
<scrollbar />
</window>
</canvas>


This OpenLaszlo example provide several observations about OpenLaszlo development. First, this example shows how easy it is to have OpenLaszlo access server-side XML resources using the <dataset> tag:


<dataset name="blogRssFeed"
request="true"
src="http://marxsoftware.blogspot.com/feeds/posts/default?alt=rss" />


The dataset tag example shown above uses only three lines to associate a handle/name with the dataset called "blogRssFeed", instructs OpenLaszlo to initialize the dataset immediately, and provides the URL from which to access the data. I could have added the attribute type="http" to explicitly instruct OpenLaszlo that this data is obtained from an HTTP connection (rather than from a file), but using "http://" in the src attribute did essentially the same thing.

This sample blog RSS reader also provides examples of one of OpenLaszlo's most powerful features, the ability to use constraints. Constraints are easily identifiable by the ${---} syntax (similar to Ant properties syntax). In this example, I did not declare a constraint compiler directive, so it is implicitly assumed the compiler directive is always. Used this way, these constraints instruct OpenLaszlo to update attribute values immediately when the value to which they are constrained is updated.

A third interesting observation from this simplistic OpenLaszlo-based RSS Reader is the use of richinputtext with textformat:


<richinputtext name="rssFeedLink"
text="$path{'link/text()'}"
fontsize="12"
resize="true"
width="${parent.width*0.9}"
selectable="true">
<handler name="ontext">
htmlLink = new textformat(); // LzTextFormat is deprecated
htmlLink.setAttribute("url", this.getText());
htmlLink.setAttribute("target", "blank");
this.setHTML(htmlLink);
this.setTextFormat(htmlLink);
</handler>
</richinputtext>


In the snippet above, a handler is specified for the richinputtext element by nesting the handler element within the richinputtext element and providing the type of event it should handle (ontext) via the name attribute of handler.

The snippet above also demonstrates use of textformat (replaces the deprecated LzTextFormat and intended for script [not LZX XML markup] only). It also demonstrates using textformat in conjunction with the richinputtext element to create HTML text. In this case, it creates an HTML link to the designated RSS feed URL and does so in a new browser window.

Although this example provides several additional interesting things to highlight, I'll end this entry with one more thing of personal interest. Several pieces of the OpenLaszlo application take advantage of OpenLaszlo's XPath syntax support to query XML from the dataset populated via the RSS feed URL. The ability to use XPath syntax is advantageous because of its familiarity to those who have used XPath in other things (such as XQuery or XSLT), because of the standard nature of XPath, and because of the expressive but concise nature of XPath syntax.

In this blog entry, I've attempted to demonstrate by example that OpenLaszlo supports several standards including XML, XPath, HTTP, and ECMAScript. OpenLaszlo also supports an implementation of the de facto "standard" XMLHttpRequest for non-XML data handling. With OpenLaszlo's basis in and support of common web development standards, it is a relatively easy technology to learn and apply.




UPDATE (14 July 2008): There are a couple of updates to note related to this OpenLaszlo-based RSS Reader. They are listed next with hyperlinks to more details.


* OpenLaszlo 4.1 no longer supports textformat as used above, but it must be used as lz.textformat() instead -- see textformat NOT AWOL in OpenLaszlo 4.1 for more details.

* Tooltips can be added to the RSS Reader to make it more user-friendly as described in OpenLaszlo ToolTips.

3 comments:

Unknown said...

Thank you for sharing your code with us.

I have written a similar application specific to my needs, based on your blog entry.

When I compile your application and mine to a SOLO application, they do not work on my server.

The OpenLaszlo debugger message highlights the crossdomain.xml file. I have put the file at the root of my serve. This did not fix the issue.

Does the crossdomain.xml file need to be on my server or on the blogspot.com server?

Any help would be appreciated.

Richard

@DustinMarx said...

Thanks, Richard, for your comment.

I am especially appreciative of your question because it reminds me of something I should have addressed in the blog entry, but forgot to do so.

What you have run into is an intentional Flash Player security restriction (see Using cross-domain policy files).

Unfortunately (in this case), the crossdomain.xml file needs to be placed in the target server from which you are trying to load the XML data to allow the Flash Player to load data from a server other than that from which the Flash Player was started. Because the Flash Player does not allow you to load or access data from a remote site that doesn't have a crossdomain.xml file configured to allow you access, you need to use a proxy through which you can access that data. This is why it works for proxy mode, but not for SOLO mode in your case.

I have run into this issue in both my Flex and my OpenLaszlo development. As you have seen, the way to get around this in OpenLaszlo when you don't have control of the server is to use the OpenLaszlo proxy (not SOLO) as documented by Don Hopkins under the section "What Are Flash's Limitations" in the entry What is OpenLaszlo and What is It Good For?. Similarly, in Flex, the most obvious approach is the proxy concept as well, implemented as BlazeDS in Flex.

Cross-Domain 101 and OpenLaszlo Crossdomain.xml Files for Flash Access provide additional details on the crossdomain.xml file.

This is probably more verbose than what you were looking for, but it is the type of detail I had wanted to include in the blog entry, but neglected until you mentioned it.

Thanks again.

Dustin

Unknown said...

Dusten,

Thank you very much for your quick and detailed reply. I'm still working my way through.

I have been investigating how to add the crossdomain.xml file the blogspot. So far no luck. I have publisher rights to the blog, so if I knew how -- I could do it.

I may also try installing OpenLaszlo on my webserver.

Thanks again for all your help.

Richard