Serving data from a Vaadin portlet

Hello,

I’m working on a series of articles on Vaading with a special focus on Groovy and Grails.

So I develop a small demonstration application that displays a Fusion Chart’s bar graph in order to show the evolution of the temperature.
For that, I reused the code found in this forum (thank you to Sami).

The application works well as a classical web application deployed on Tomcat.

An Embedded object is used to represent the flash object that will use the Flash file Column3D.swf available in the Java package.


ClassResource chartResource = new ClassResource("Column3D.swf", mainWindow.getApplication());

// The Embedded component to present the Flash object
Embedded chart = new Embedded(null, chartResource);

// Set size properties for the chart
chart.setWidth("500px");
chart.setHeight("400px");
        
// dataUrl maps to URIHandler below.
chart.setParameter("FlashVars", "dataUrl=mydata.xml");

When displayed, the Flash component will fetch its data from the URL “data.xml” (defined in “dataUrl=mydata.xml” ); in the code, the data is served by an URIHandler with something like:


mainWindow.addURIHandler(new URIHandler() {
            private static final long serialVersionUID = 1L;

            public DownloadStream handleURI(URL context, String relativeUri) {
                if (relativeUri.startsWith("mydata")) {  
                	String xml = "<chart caption='Températures maximales sur 5 jours' subcaption='Antibes, France' xAxisName='Jours' yAxisName='Températures' numberSuffix='°C'>"+
                		"<set label='Oct 20' value='15.0' /><set label='Oct 21' value='16.1' /></chart>";	
                	ByteArrayInputStream bais = new ByteArrayInputStream(xml.getBytes());
                	return new DownloadStream(bais, "application/xml", relativeUri);
                }
                return null;
            }
        });

What’s the problem then?

Well, I’m trying to port this application as a
portlet
deployed in Liferay 6.

The point that doesn’t work is the data URL of course ; without modification, the Flash component shows the error message “Error in loading data”, and in the console I get this message:

14:12:00,320 INFO  [PortalImpl:3812]
 Current URL /web/guest/Data.xml?FCTime=109 generates exception: null

Note that it’s not mydata.xml!

My question is: how can I construct an URL in order the application can handle the request for the data?

I tried a lot of code but without success, for example, by using the PortletApplicationContext2 instance in order to generate an URL to use.

Any idea?

Cheers,

Bertrand.

Finally I made some progress, and found a solution that is more a workaroud.

First, the message in the console

14:12:00,320 INFO  [PortalImpl:3812]
 Current URL /web/guest/Data.xml?FCTime=109 generates exception: null

is explained by the fact that the FusinCharts graph could not load the data from the URL, and by default try to fetch the data from Data.xml.

I succeeded to build a valid URL like this:

PortletApplicationContext2 ctx = (PortletApplicationContext2) application.getContext();
String url = ctx.generateApplicationResourceURL(new FileResource(new File("mydata.xml"), application), "mykey");
try {
    url = URLEncoder.encode(url, "UTF-8");
} catch (UnsupportedEncodingException e) {
    e.printStackTrace();
}
		
chart.setParameter("FlashVars", "&dataUrl="+url);

And the data is served like this:

mainWindow.addURIHandler(new URIHandler() {
    private static final long serialVersionUID = 1L;

    public DownloadStream handleURI(URL context, String relativeUri) {
        if (relativeUri.endsWith("mydata.xml")) {  
            String xml = "<chart caption='Températures maximales sur 5 jours' subcaption='Antibes, France' xAxisName='Jours' yAxisName='Températures' numberSuffix='°C'>"+
"<set label='Oct 20' value='15.0' /><set label='Oct 21' value='16.1' /></chart>";    
            ByteArrayInputStream bais = new ByteArrayInputStream(xml.getBytes());
            return new DownloadStream(bais, "application/xml", relativeUri);
        }
        return null;
    }
});

The key points are to get an URL from the PortletApplicationContext2 instance and to encode the URL.

But… It works well in FireFox 3.6.x but not in Chrome 6.0.x.

The data is not fetched by Chrome, and I don’t know why for the moment.

So, I decided to try a new approach; in order to have more control on the HTML code injected for Flash, I used a Label with a XHTML content to generate the necessary HTML code for include the Flash component with the correct URLs: one for the Column3D.swf, and one for the data.
In this case my handleURI method must process two requests to serve the Column3D.swf and the XML data for the graph.
And it works !!

I think it would be better to serve Column3D.swf in a static way, instead of code like this:

if (relativeUri.endsWith("Column3D.swf")) {
    InputStream is = getClass().getResourceAsStream("Column3D.swf");
    return new DownloadStream(is, "application/x-shockwave-flash", relativeUri);
}

Any suggestion or idea?

Cheers,

Bertrand