Flex, BlazeDS and JPA

After several days of playing with Flex, I’ve managed to create a simple Java-based backend using BlazeDS and the Java Persistence API (JPA).

In this post, we will try to implement what used to be a very popular application (during the early days of the Internet), the “Guest Book“.

What you’ll need:

The assumption here is that you are already comfortable with Java and databases, and you just want to know how to make your Flex application communicate to your Java backend.

We now proceed to creating our form Using Flex Builder.

guestbook.mxml

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
    layout="absolute" xmlns:local="*">
 <mx:Form x="10" y="10" width="270" height="150">
 	<mx:FormItem label="Name">
 		<mx:TextInput id="guestname" />
 	</mx:FormItem>
 	<mx:FormItem label="Message">
 		<mx:TextArea id="guestmessage" />
 	</mx:FormItem>
 	<mx:FormItem label="">
 		<mx:Button label="Submit" />
 	</mx:FormItem>
 </mx:Form>
</mx:Application>

Switching to “Design” view should show us the form that we just created.

Look how nice and easy it was to create the form.

But wait, this application doesn’t do anything yet, so let’s move on to adding some logic.

Let’s try to modify the submit button to call our remote object:

<mx:Button label="Submit"
    click="guestBookService.add(guestBookEntry)"/>

Adding this line alone will cause a compile error because we haven’t told Flex what the guestBookService and guestBookEntry objects are all about.

First we need to create an ActionScript class named GuestBookEntry.as which will correspond to our remote JPA entity named GuestBookEntry.java (located under the guestbook package).

package
{
    [Bindable]
    [RemoteClass(alias="guestbook.GuestBookEntry")]
    public class GuestBookEntry
    {
        public function GuestBookEntry()
        {
        }

        private var _guestName:String;
        private var _guestMessage:String;

        public function get guestName():String {
            return _guestName;
        }

        public function set guestName(guestName:String):void {
            _guestName=guestName;
        }

        public function get guestMessage():String {
            return _guestMessage;
        }

        public function set guestMessage(guestMessage:String):void {
            _guestMessage=guestMessage;
        }
    }
}

Notice how the constructor, setters and getters are different from how you would normally do it in Java.

We now update guestbook.mxml to include a reference to our guestBookEntry object (also called a custom component). This should be added as a child of the Application element.

<local:GuestBookEntry id="guestBookEntry"
    guestName="{guestname.text}"
    guestMessage="{guestmessage.text}" />

The curly braces mean that any changes to the text values of the form elements in guestbook.mxml would be directly applied to the guestBookEntry instance.

That should leave us with one more compile error to deal with, which is that of the missing reference to guestBookService.

Just add the fragment below as a child to Application and we’re all done! At least with the Flex part.

<mx:RemoteObject id="guestBookService"
    destination="guestBookService"
    source="guestbook.GuestBookService"
    channelSet="{cset}"/>
<mx:ChannelSet id="cset">
    <mx:channels>
        <mx:AMFChannel id="myamf"
            uri="http://localhost:8400/guestbook/messagebroker/amf"/>
    </mx:channels>
</mx:ChannelSet>

I’m sorry if I cannot explain the ChannelSet details as of now, because I’m as clueless as you are. We just need to make sure that they match the values in our BlazeDs backend and we’re good to go.

From your turnkey download, locate a file named blazeds.war, if you’ve done some Struts programming before, this is the same as the struts-blank.war which can serve as a template for new projects.

Import this war as a project in Eclipse WTP, and name this project guestbook (remember that our backend needs to match the entries we added for the RemoteObject and ChannelSet).

When you’re done setting up the project in Eclipse, navigate to “WEB-INF\flex\”. At this point we are only interested in “remoting-config.xml” where we should be defining a reference to our remote object.

Add these lines in between the adapters and default-channels:

   <destination id="guestBookService">
<properties>
         <source>guestbook.GuestBookService</source>
      </properties>
   </destination>

To setup JPA, we need to create a folder named META-INF under src and create a file named persistence.xml. Also, make sure to add TopLink JPA jars and your JDBC driver to WEB-INF\lib.

<?xml version="1.0" encoding="UTF-8"?>
<persistence version="1.0"
 xmlns="http://java.sun.com/xml/ns/persistence"
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd">
<persistence-unit name="guestbook" transaction-type="RESOURCE_LOCAL">
<provider>
           oracle.toplink.essentials.PersistenceProvider
        </provider>
        <class>guestbook.GuestBookEntry</class>
<properties>
<property name="toplink.ddl-generation" value="drop-and-create-tables"/>
<property name="toplink.jdbc.driver" value="com.mysql.jdbc.Driver"/>
<property name="toplink.jdbc.url" value="jdbc:mysql://localhost:3306/guestbook"/>
<property name="toplink.jdbc.password" value="guestbook"/>
<property name="toplink.jdbc.user" value="guestbook"/>
 	</properties>
 </persistence-unit>
</persistence>

We now create the Java objects GuestBookService and GuestBookEntry:

@Entity
public class GuestBookEntry {

    @Id
    @GeneratedValue(strategy = GenerationType.TABLE)
    private long id;

    private String guestName;
    private String guestMessage;

    public GuestBookEntry() {}

    // getters and setters
}
public class GuestBookService {

    private EntityManagerFactory emf = null;

    public EntityManagerFactory getEMF() {
        if (emf == null) {
            emf = Persistence.createEntityManagerFactory("guestbook");
        }
        return emf;
    }

    public void add(GuestBookEntry guestBookEntry) {
        EntityManager em = getEMF().createEntityManager();
        try {
            em.getTransaction().begin();
            em.persist(guestBookEntry);
            em.getTransaction().commit();
        } catch (Exception e) {
            em.getTransaction().rollback();
            e.printStackTrace();
        } finally {
            em.close();
        }
    }

}

The guestbook.war can be downloaded from this location. The file uses an odt extension because of hosting limitations. Please rename to .war accordingly.

Also, JAR files from BlazeDS, TopLink and MySQL driver were not included in the distribution.

Let me know if you encounter any problems while running the application.

Recommended books:

1933988746 1933988347

Advertisements

11 Comments »

  1. Andy said

    Thanks for the post! I’m working on Flex + JPA integration too.

    So if you didn’t create the Flex custom component to support the GuestBookEntry Java class, is there any way in Flex3 to introspect the object returned by the method call on the RemoteObject?

    I’d been playing with the idea of exposing JPA’s EntityManager.find method directly via something like this:

    public class EntityManagerFacade {
    public T find(Class entityClass, Object entityId) throws Exception {
    return entityManager.find(entityClass, entityId);
    }
    }

  2. kris said

    SELAMAT DATANG
    silahkan isi sobat

  3. kris said

    Selamat Datang

  4. Alexandr said

    Im get following error:

    faultCode = “Server.ResourceUnavailable”
    faultDetail = “The expected argument types are (example.GuestBookEntry) but the supplied types were (flex.messaging.io.amf.ASObject) and converted to (null).”

    Or the package names need to match exactly on the server and the client?

  5. dayg said

    Hi Alexander,

    Were you able to change the value for this annotation in your ActionScript class?

    [RemoteClass(alias=”guestbook.GuestBookEntry”)]

    Make sure you update this according to the package name of your server side classes.

    Let me know how it works!

    Thanks.

  6. Alexandr said

    Can you mail me the source code? I’m 3d day trying to figure out why it don’t working for me :-)

  7. Alexandr said

    I’m using Glassfish server, but I’m don’t think that problem in it

  8. Alexandr said

    (: it’s all right … thanks for your work

  9. Tom said

    Can you mail me the source code?. Thanks

  10. dayg said

    Sorry for the late response, but the sources should arrive shortly in your inbox.

  11. Tanzeem Akhtar Bhatti said

    Please send me the source code……
    Tnanks
    Tanzeem Akhtar Bhatti
    Flex Developer
    Rich Applications Consulting(pvt) ltd

RSS feed for comments on this post · TrackBack URI

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: