Wednesday, 27 May 2009

News from Google Developer I/O


Google giving away free Android Phones with a local operator sim allowing free unlimited local calls and free data access to let us try android! OMG i wonder what's nect will they give us free macbooks to try GWT :) well hope so...

Sunday, 24 May 2009

Flex Remoting on Google App Engine

I'm not personally related to Adobe, Google nor Sun but I like to code in Java, I am happy to see what Adobe filling the gap which Sun left years ago with applets. Java is the perfect choice to use on Google App Engine. So can Flex also be a good choice to use with both? Last episode we let Anakin meet Obi Wan Kenobi, now time to see how they do together in harder missions. Lets dive deeper and see...

I assume you have basic knowledge about GAE and its eclipse plugin, if not go back to the previous article and do some coding because this part will be tough. I also assume you know what is Flex (or at least RIA) and what does it offer else you can do this tutorial with any other web framework and still achieve what we will.

Last article we managed to code a very basic servlet which returns and receives xml from our Flex client which had hard coded tags as strings. Of course in real world you wouldn't want this and probably use xstream or any other parser to convert our objects to xml but wouldn't it be great to call Java backend from our flex client with remoting and using objects without xml serilization. Well this episode we are going to build some spring beans on GAE and make them available as BlazeDS remoting for our Flex client.

Again if you didn't try the previous post or not comfortable with GAE go and try it.
Lets make a Head First style intro, our boss and clients were happy with the phonebook project we built in last part but soon they will be demanding better performance and more functionality so lets refactor our previous project and turn it into a more sophisticated one.
Create a new GAE project just like the previous one this time lets name it SecondProject.


Again the plugin created an example for us, lets forget about them and start with our entity. Create a Java class under org.flexjava.server package.
package org.flexjava.server;

import javax.jdo.annotations.IdGeneratorStrategy;
import javax.jdo.annotations.PersistenceCapable;
import javax.jdo.annotations.Persistent;
import javax.jdo.annotations.PrimaryKey;

@PersistenceCapable
public class Entry {
@PrimaryKey
@Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY)
Long id;

@Persistent
private String name;

@Persistent
private String phone;

public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
//getters setters
}


Create a new interface FlexService under org.flexjava.server package with following method declarations.

package org.flexjava.server;

import java.util.List;

public interface FlexService {
public boolean addEntry(Entry entry);
public List <Entry> getEntryList();
}


This two methods will be enough to achieve our goal. Now under the same package create FlexServiceImpl class and add the methods with the knowledge we gained from our previous application.

package org.flexjava.server;

import java.util.List;
import javax.jdo.JDOHelper;
import javax.jdo.PersistenceManager;
import javax.jdo.PersistenceManagerFactory;
import javax.jdo.annotations.Transactional;

public class FlexServiceImpl implements FlexService {
//persistance manager
private static final PersistenceManagerFactory pmfInstance = JDOHelper
.getPersistenceManagerFactory("transactions-optional");
PersistenceManager persistenceManager;

@Override
@Transactional
public boolean addEntry(Entry entry) {
try {
//check if the id is 0 which is same as null
if (entry.getId().intValue()==0){
entry.setId(null);
}
//get manager
persistenceManager = pmfInstance.getPersistenceManager();
//save our entry
persistenceManager.makePersistent(entry);
return true;
} catch (Exception e) {
return false;
}
}

@Override
@Transactional
@SuppressWarnings("unchecked")
public List<Entry> getEntryList() {
//get persistance manager
persistenceManager = pmfInstance.getPersistenceManager();
//our query which is a select * in this case
String query = "select from " + Entry.class.getName();
//return the result
return (List<Entry>) persistenceManager.newQuery(query).execute();
}
}

Compared to the last tutorial our server side code is much more simpler. Before going into dungeons of configuration files lets code the flex end. Click on the project and add Flex nature. Do not forget to change the output folder to “war” folder of the project. To use remoting we need the ActionScript counterpart of our Entry object. Create a new ActionScript object under org.flexjava.client package.

package org.flexjava.client
{
[Bindable]
[RemoteClass(alias="org.flexjava.server.Entry")]
public class Entry
{
public var id:int;
public var name:String;
public var phone:String;
public function Entry()
{
}

}
}



The remote class alias must be pointing exactly to your Java object. Since we done this we are ready to finish our Flex client. It will be very similar to the previous phonebook application.


<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" initialize="init()">
<mx:TextInput x="114" y="20" id="nameTxt"/>
<mx:TextInput x="114" y="60" id="phoneTxt"/>
<mx:Label x="29" y="22" text="Name"/>
<mx:Label x="29" y="62" text="Phone"/>
<mx:Button x="332" y="60" label="Save" click="saveEntry()"/>
<mx:DataGrid id="grid" x="29" y="138" dataProvider="{phonebook}">
<mx:columns>
<mx:DataGridColumn headerText="Name" dataField="name"/>
<mx:DataGridColumn headerText="Phone" dataField="phone"/>
<mx:DataGridColumn headerText="Record Id" dataField="id"/>
</mx:columns>
</mx:DataGrid>
<mx:RemoteObject id="ro" result="showEntryList(event)" destination="FlexDestination" endpoint="http://localhost:8080/messagebroker/amf"/>
<mx:Script>
<![CDATA[
import mx.binding.utils.BindingUtils;
import org.flexjava.client.Entry;
import mx.collections.ArrayCollection;
import mx.rpc.events.ResultEvent;
import mx.controls.Alert;
[Bindable]
public var phonebook:ArrayCollection;

public function init():void{
ro.getEntryList();
}
public function saveEntry():void{
var entry:Entry=new Entry();
entry.name=nameTxt.text;
entry.phone=phoneTxt.text;
ro.addEntry(entry);
}
public function showEntryList(event:ResultEvent):void{
if (event.result!=null){
if (event.result==false){
Alert.show("record could not be added");
}else if (event.result==true){
Alert.show("added to your phone book");
ro.getEntryList();
}else{
phonebook=event.result as ArrayCollection;
}
}
}
]]>
</mx:Script>
</mx:Application>

This way the Flex client looks simpler too. We are done with coding and it was still quite easy. Lets do the spring and blaze configuration. If you ever googled Flex-Java and Blaze you probably ended up at Christophe Coenraets blog. He was one of first people I heard and learned flex from. He offers great examples and a zipped and configured tomcat with everything necessary (from blaze, activemq, database, spring etc..). Spring source also offers a great documentation about Spring-Blaze integration. We will definitely need this two to continue.

Locate web.xml under war\WEB-INF folder and add the following inside the web-app tags.

 <!-- Spring -->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>WEB-INF/webAppContext.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>

<servlet>
<servlet-name>testdrive</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>

<servlet-mapping>
<servlet-name>testdrive</servlet-name>
<url-pattern>/messagebroker/*</url-pattern>
</servlet-mapping>

Now create a webAppContext.xml next to web.xml.

<?xml version="1.0" encoding="utf-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:flex="http://www.springframework.org/schema/flex"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/flex
http://www.springframework.org/schema/flex/spring-flex-1.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-2.5.xsd">

<flex:message-broker>
<flex:message-service
default-channels="my-streaming-amf,my-longpolling-amf,my-polling-amf" />
<!-- <flex:secured /> -->
</flex:message-broker>

<bean id="flexBean" class="org.flexjava.server.FlexServiceImpl"/>
<!-- Expose the productDAO bean for BlazeDS remoting -->
<flex:remoting-destination destination-id="FlexDestination" ref="flexBean" />

</beans>

This will make our FlexServiceImpl class available a Spring bean called flexBean. Next we enable this spring bean as a blaze remoting destination with the id of FlexDestination. FlexDestination will be the name exposed to outer world to call our service class with remoting.

Now create a folder named flex under WEB-INF and add the following four flex xml configuration files. Those files are quite standart so if you had downloaded Christophe's example or got them any other way, you may just copy those files instead of creating.


Finally the jar list. Actually I just copy the jars Christophe's server, I know most of the jars we won't be using (specially database one) but still I took them all to be able to add new functionality to my project.

antlr-3.0.1.jar
aopalliance.jar
appengine-api-1.0-sdk-1.2.0.jar
aspectjrt.jar
aspectjweaver.jar
backport-util-concurrent.jar
cglib-nodep-2.1_3.jar
commons-codec-1.3.jar
commons-httpclient-3.0.1.jar
commons-logging.jar
concurrent.jar
datanucleus-appengine-1.0.0.final.jar
datanucleus-core-1.1.0.jar
datanucleus-jpa-1.1.0.jar
flex-messaging-common.jar
flex-messaging-core.jar
flex-messaging-opt.jar
flex-messaging-proxy.jar
flex-messaging-remoting.jar
geronimo-jpa_3.0_spec-1.1.1.jar
geronimo-jta_1.1_spec-1.1.1.jar
gwt-servlet.jar
jackson-core-asl-0.9.9-6.jar
jdo2-api-2.3-SNAPSHOT.jar
org.springframework.aop-3.0.0.M3.jar
org.springframework.asm-3.0.0.M3.jar
org.springframework.aspects-3.0.0.M3.jar
org.springframework.beans-3.0.0.M3.jar
org.springframework.context-3.0.0.M3.jar
org.springframework.context.support-3.0.0.M3.jar
org.springframework.core-3.0.0.M3.jar
org.springframework.expression-3.0.0.M3.jar
org.springframework.flex-1.0.0.RC1.jar
org.springframework.jdbc-3.0.0.M3.jar
org.springframework.jms-3.0.0.M3.jar
org.springframework.transaction-3.0.0.M3.jar
org.springframework.web-3.0.0.M3.jar
org.springframework.web.servlet-3.0.0.M3.jar
spring-security-acl-2.0.4.jar
spring-security-catalina-2.0.4.jar
spring-security-core-2.0.4.jar
spring-security-core-tiger-2.0.4.jar
spring-security-taglibs-2.0.4.jar
xalan.jar
So far we did everything as we are instructed so we expect everything to run smoothly. Right click and run your project as Web Application.

"Channel.Connect.Failed error NetConnection.Call.Failed: HTTP: Status 500: url: 'http://localhost:8080/messagebroker/amf'"
Ok, we weren't expecting this but if we check our server logs we will notice a clue;
WARNING: /messagebroker/amf
java.lang.RuntimeException: Session support is not enabled in appengine-web.xml. To enable sessions, put true in that file. Without it, getSession() is allowed, but manipulation of sessionattributes is not.
at com.google.apphosting.utils.jetty.StubSessionManager$StubSession.throwException(StubSessionManager.java:67)

Great! Google even tells us what to do, this is what I expect from a framework. Open the appengine-web.xml file and add ”true” just before the system-parameters tag. Lets re run the server and our application works! Well not that hard, actually it is time to deploy our code in to the Google Cloud and see it working there.
First goto your SecondProject.mxml file and change the endpoint value with your app url(in mine; endpoint="http://flexjava2p.appspot.com/messagebroker/amf"). Click the Deploy App Engine project button, and enter your email and password. Of course if you don't have an GAE account first create one.



The plugin recompiles and deploys our project. Now open a browser and type your url. Ok this was the first real suprise GAE introduced to me. So far GAE offered a reliable and stable development and production environment but now we face an error which we can not reproduce in our development environment “flex.messaging.request.DuplicateSessionDetected “.
When I search for this error I found another good resource. In this post Martin tells us about the problem and how he solved by editing flex-messaging-core.jar. This incident cools down my excitement about GAE/Flex but still you can see how important it is to work with open source frameworks. I asked Martin to send me his custom jar and (thanks to him) I included the jar in the project export. Besides the custom jar file, go to services-config.xml and add "<manageable>false</manageable>" just after the system tag.
Feel lost? Do not.. GAE Java is just in the early stage and even getting to this point with even Flex which is totally out of Java environment is still a great success. As long as we have the opened source we will have solutions like Martin Zoldano's.
I remember reading the following on Yakov Fain's blog;
“99% of the people who reject using the software until it gets open sourced, neither plan nor will look at its source code. “

I agree most people do not look at the source code even if they need but I post a comment saying;
“Well probably same amount of people who buy cars equipped with airbags also don'use the airbags (so far i didn't) but it can be very helpful if you are in need “.

So when choosing your car don't forget to get a one with airbags even if you feel you don't need them.

Tuesday, 12 May 2009

Flex meets Google App Engine

Adobe did a very good job with Flex and they are far ahead of their rivals in RIA area. Meanwhile google is doing great with several java projects (such as guice, gwt) and bringing Java support to Google App Engine. Actually Google even has an open source Flex components library called flexLib.
Java on Google App Engine is a very important step. Since I graduaded i hear most of friends bringing up ideas but not trying to built them, mostly because of the costs of Java hosting. Java is a elegant and sophisticated platform which is very fun to work on but never offers cheap and easy hosting alternatives like PHP. Google App Engine can finally change this, it offers zero cost startup, flexible payment options as your project grows and also provides a very easy development environment. All you need is just to install the eclipse plugin and start coding. Even when a new GAE project is created, a basic GWT example is already included.
I really like the scene Obi-wan Kenobi meets Anakin Skywalker in Episode I. Qui-Gon introduces Anakin and says “Anakin Skywalker meet Obi-Wan Kenobi”. It is an important scene bringing two different people together for a very long time.
This post will be an intoduction of Flex to Google App Engine. Two great but totally different worlds. We will build a very basic servlet to feed data to our Flex application, and use Google's datastore to easily persist the data. Before starting the tutorial I assume GAE plugin and Flex builder plugin is already installed to your Eclipse instance.
You must have noticed the new three buttons on toolbar. Just click the “New Web Application Project”.



Next give a package and project name.



You must have noticed the wizard already added GreetingService, GreetingServiceImpl and a GWT class with the name of your project (in this case “FirstProject”). This is a good start specially for starting GWT but not usefull for us. Just leave them there and open web.xml file under war/WEB-INF and add a servlet description.



We are ready to create a servlet to feed our Flex Client. Right click org.flexjava.server package and add a new class file extending HttpServlet as shown below.



Now its time to design our backend service. I don't really like hello world projects so even if we are coding a basic project lets find a real (but still basic) phonebook project worth to code. For the basic functionality we need retrieve the list of the contacts stored in the datastore and we also need to add new ones.
We need an Entity for our contacts. Lets create a new Class named Entry and add the annotations to make our Entry class persistamce capable.

package org.flexjava.server;

import javax.jdo.annotations.IdGeneratorStrategy;
import javax.jdo.annotations.PersistenceCapable;
import javax.jdo.annotations.Persistent;
import javax.jdo.annotations.PrimaryKey;

@PersistenceCapable
public class Entry {
@PrimaryKey
@Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY)
Long id;
@Persistent
private String name;
@Persistent
private String phone;

public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
// Add all getter/setters...
}

GAE's datastore is quite easy to use. Just create a persistanceManager and use makePersistant or newQuery methods to save or retrieve data.
PersistenceManager persistenceManager = pmfInstance.getPersistenceManager();
//..
persistenceManager.makePersistent(entry);
//..
persistenceManager.newQuery(query).execute();

Lets start coding our servlet using those.

package org.flexjava.server;

import java.io.IOException;
import java.io.PrintWriter;
import java.util.List;

import javax.jdo.JDOHelper;
import javax.jdo.PersistenceManager;
import javax.jdo.PersistenceManagerFactory;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@SuppressWarnings("serial")
public class FlexServiceImpl extends HttpServlet {
//persistanceManager
private static final PersistenceManagerFactory pmfInstance = JDOHelper.getPersistenceManagerFactory("transactions-optional");

@SuppressWarnings("unchecked")
public void doGet(HttpServletRequest req, HttpServletResponse resp)
throws IOException {
//PrintWriter to return and receive data from flex client
PrintWriter writer=resp.getWriter();
writer.println("\n");
PersistenceManager persistenceManager = pmfInstance.getPersistenceManager();
//reading parameters from http request
String operation = req.getParameter("operation");
String name = req.getParameter("name");
String phone = req.getParameter("phone");
//if adding new contact is requested
if (operation.equalsIgnoreCase("save")){
Entry entry=new Entry();
entry.setName(name);
entry.setPhone(phone);
persistenceManager.makePersistent(entry);
writer.println("Success");
//if retrieving all contact list is requested
}else if (operation.equalsIgnoreCase("get")){
//Query to retrieve all Entry data
String query = "select from " + Entry.class.getName();
List entries = (List) persistenceManager.newQuery(query).execute();
writer.println("");
for (Entry entry : entries) {
writer.println("");
writer.println(""+entry.getName()+"");
writer.println(""+entry.getPhone()+"");
writer.println("
");
}
writer.println("
");
}
}
}

Our GAE code is ready, now we can move on to Flex. To enable our project Flex compatible, right click project and select add Flex Project Nature.



Click next to continue.



Select war folder as the output folder so the build files will be deployed to server.



Since we just added Flex nature and created a mxml file, Flex Builder finds it confusint to prepare the html wrapper files for the swf build. To make Flex builder's life easier go to errors tab, right click the error and select recreate HTML Templated. If there are no errors just skip this and continue.



Now we are free to design our own user interface. Switch to design view drag and drop 2 labels, 2 text boxes, a button and a datagrid component.



Now we can switch to source mode to code. We are going to use very little coding, most of the work will be done by auto XML parsing and binding the data between components and variables.

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" initialize="callService('get')">
<mx:TextInput x="114" y="20" id="nameTxt"/>
<mx:TextInput x="114" y="60" id="phoneTxt"/>
<mx:Label x="29" y="22" text="Name"/>
<mx:Label x="29" y="62" text="Phone"/>
<mx:Button x="332" y="60" label="Save" click="callService('save')"/>
<!-- datagrid is directly binded to phonebook variable -->
<mx:DataGrid x="29" y="138" dataProvider="{phonebook.entry}">
<mx:columns>
<!--datafields determine which property belongs to that column-->
<mx:DataGridColumn headerText="Name" dataField="name"/>
<mx:DataGridColumn headerText="Phone" dataField="phone"/>
<mx:DataGridColumn headerText="Record Id" dataField="@id"/>
</mx:columns>
</mx:DataGrid>
<!--HTTPService can easily post and receive xml data-->
<mx:HTTPService id="httpXmlDataService"
url="http://localhost:8080/firstproject/flex"
resultFormat="e4x"
result="resultHandler(event)"
useProxy="false">
<!--xml request will be automatically formed with bindings-->
<mx:request xmlns="">
<operation>{command}</operation>
<name>
{nameTxt.text}
</name>
<phone>
{phoneTxt.text}
</phone>
</mx:request>
</mx:HTTPService>
<mx:Script>
<![CDATA[
import mx.collections.ArrayCollection;
import mx.rpc.events.ResultEvent;
[Bindable]
private var command:String;
[Bindable]
private var phonebook:XML;
//xml var to hold the received data,note bindable attribute
//to enable binding

public function resultHandler(event:ResultEvent):void{
if (event.result!=null){
var xml:XML=event.result as XML;
if (xml.result=="success"){
callService("get");
}else{
phonebook=xml;
}
}
}
public function callService(command:String):void{
this.command=command;
httpXmlDataService.send();
}
]]>
</mx:Script>
</mx:Application>

So little and our client is ready, right click the project and select run as Web Application.



GAE Plugin adds an embedded datastore and a server to your project to test. Whenever you click run the embedded services will be running and even an internal browser will run your client. Since our project name and mxml file has the same name, the default page on web.xml file point to our Flex application. Please dont forget to modify in your web.xml file if yours differ.



Easy? Well yes but still this does not release the real power and integration of Java and Flex. Next time we will focus on BlazeDs to make Flex to talk to Google App Engine. Stay tuned ;)

p.s. While waiting, start coding your dreams for free and keep in mind if you are interested in depth details of Flex, eteration offers a new training course which i also act part in the preperation.