Login | Register   
Twitter
RSS Feed
Download our iPhone app
TODAY'S HEADLINES  |   ARTICLE ARCHIVE  |   FORUMS  |   TIP BANK
Browse DevX
Sign up for e-mail newsletters from DevX


advertisement
 

Flex RESTing with MySQL : Page 2

This infrastructure will allow you to focus on your application's look and feel to create more elaborate and elegant Flex applications.


advertisement
The REST architecture recommends that developers use the HTTP methods explicitly on their resources:
    * Use HTTP POST to create a resource.
    * Use HTTP GET to retrieve a resource.
    * Use HTTP PUT to update a resource.
    * Use HTTP DELETE to delete a resource.
Because of a browser limitation, Adobe Flash Player is unable to issue any PUT or DELETE methods. To get around this recommendation, I use a modified REST implementation as follows:
    * Use the GET method for deletion when the client passes a query parameter of deleteFlag set to 1.
    * Use the POST method to update whether the client includes a valid ID. If the ID is not provided or is invalid, then the service creates a new resource.
Here is my modified RESTful Web service API:

@GET @Path("{bookid}") @Produces("application/xml") public String getBook(@PathParam("bookid") String bookid, @DefaultValue("0") @QueryParam("deleteFlag")
int deleteFlag){} @POST @Consumes("application/xml") @Produces("application/xml") public String addOrUpdateBook(String bookContent) {} @GET @Produces("application/xml") public String getBooks() {}

This API is just one implementation to get around this limitation. Feel free to choose the best workaround for your application. The REST architecture is flexible enough to support quite a few solutions.

Using Spring DAOs in My RESTful Resource



As mentioned earlier, to access my database, I take advantage of Spring DAOs that ibator generates. To tie my DAO to my RESTful resource, I turn to Spring annotation again. I just add my Spring DAO as a member of my Java REST resource class with some Spring annotation sprinkled on top. @Autowire is a Spring annotation to inject a property into a Spring bean. Here is a Java code example to illustrate such a use:

@Path("/books") @Component @Scope("singleton") public class BookResource { @Autowired private BookDAOImpl bookDAO = null; }

Now, I can use the Spring DAOs to manage any resource in my database. The ibator-generated DAOs provide a clean interface to my database without my having to worry about any database specifics. But the real value to the generated code from ibator is the utilization of the database-defined POJOs, which are called Value Objects (VO) in Flex.

Using Value Objects

VO (also known as a Data Transfer Object) is a commonly used term in the Flex world. Think of VOs as Adobe ActionScript versions of POJOs generated from ibator. VOs are tied to the Model-View-Controller (MVC) design pattern. The model in MVC is the client-side data store for saving application data. VOs are dummy objects stored in my model and are often bound to the view of my application. On the Flex side, VOs should be the only reference to its remote services.

To use VOs in my infrastructure, I need to perform a few tasks:
    * In my Flex project, I create identical ActionScript VOs for every POJO generated from ibator.
    * In my Java project, I write the code to serialize all of the POJOs returned from my database query into XML, return the XML to my Flex client, and de-serialize the XML into VOs on the Flex side. This is simply a crude serialization process to move my VOs from server to client and vice verse. Here is Java example code utilizing XStream to serialize my database POJOs into XML:

@GET @Produces("application/xml") public String getBooks() { int i = 0; List bookList = null; String xmlStr = null; XStream xstream = null; Book book = null; Integer id = null; if (bookDAO != null) { xmlStr = "<Books>"; try { bookList = bookDAO.selectBookByExample(null); if (bookList != null && bookList.size() > 0)  { xstream = new XStream(); xstream.alias("Book", Book.class); for (i=0; i<bookList.size(); i++) { book = (Book)bookList.get(i); xmlStr += xstream.toXML(book); } } } catch (Exception e) { logger.error("getBooks: " + getStackTrace(e)); } xmlStr += "</Books>"; } else { xmlStr = "<Books />"; } return xmlStr; }

In the above code, I traverse the booklist of POJOs and pass each Book POJO into the XStream engine to be serialized into an XML string that is appended to my returning XML back to the client. This process creates a simple, manageable VO. By using VOs in my data management, I get the following benefits:
    * During Flex development, I can focus on managing the VOs, not on the how and where my application data is being stored.
    * The VOs provide a level of abstraction from the data services layer, so I am not tied to my current data service. I can change my data services layer with minimal code changes in Flex.
Using VOs in my Flex application provides some nice benefits that allow me to concentrate on creating better UIs.

Configuring Spring to Glue Everything Together

To complete my RESTful data service, there are a few ugly configuration items that I have to take care of. Using Spring, I normally reference the Spring servlet in my web.xml file, but in this case, because I am using Jersey and Spring, I have to use a custom Jersey-Spring servlet built with Spring 2.5. Here is the configuration in my web.xml file:

<servlet>        <servlet-name>Jersey Spring Web Application</servlet-name>        <servlet-class>com.sun.jersey.spi.spring.container.servlet.SpringServlet</servlet-class>        <init-param>            <param-name>debug</param-name>            <param-value>1</param-value>        </init-param>        <load-on-startup>1</load-on-startup>    </servlet>    <servlet-mapping>        <servlet-name>Jersey Spring Web Application</servlet-name>        <url-pattern>/resources/*</url-pattern>    </servlet-mapping>

Now, I must define all my resources, such as data sources and DAOs, to tie everything together. I configure them in my applicationContext.xml file. Here is my configuration:

<!- Indicates to Spring to where to find my RESTful resource --> <context:component-scan base-package="app.rest"/>      <!- Enable Spring annotations -->        <context:annotation-config />     <!- My data source -->        <bean id="myDataSource" class="org.apache.commons.dbcp.BasicDataSource"> <property name="driverClassName" value="com.mysql.jdbc.Driver"/>        <property name="url" value="jdbc:mysql://localhost:3306/restmysql?autoReconnect=true"/>        <property name="username" value="restmysql"/>        <property name="password" value="restmysql"/> </bean>     <!- My iBatis SQL Client using my data source -->      <bean id="mySqlMapClient" class="org.springframework.orm.ibatis.SqlMapClientFactoryBean">         <property name="configLocation">            <value>WEB-INF/config/my-sql-map-config.xml</value>         </property>         <property name="useTransactionAwareDataSource">             <value>true</value>         </property>         <property name="dataSource">             <ref bean="myDataSource"/>    </property>     </bean>         <!- Define my Spring DAO using iBATIS SQL Client --> <bean id="bookDao" class="app.dao.BookDAOImpl">    <property name="sqlMapClient">            <ref bean="mySqlMapClient"/>        </property>       </bean>

Using Spring to tie these technologies together is nice, but Spring offers a myriad of other features, such as database transaction, authentication, and authorization, to support a more advanced application design. In other words, as your application grows, Spring has the functionality and features to support that growth.

After finishing the Spring configuration, my RESTful resource is complete. Now, I just compile my Java source code and deploy my Web archive (WAR) to Apache Tomcat (or whatever application server is in use). For a quick test, I just point my browser to the GET method to see the resulting XML, as shown in Figure 3.

Figure 3. The XML resulting from deploying my WAR to Tomcat.

Now, I turn to the Flex side of the equation. How do I consume this RESTful resource from Flex?

Consuming My Restful Resource

After designing my RESTful data service, I am ready to start Flex development to consume the service. In this example, I am using Flex 4, but most of what I develop can be accomplished in Flex 3, as well. Flex provides a vast collection of data components, but none of them are specific to REST. Because Jersey REST is implemented over HTTP, the best option is the Flex HTTPService data component.

As I mentioned earlier, a browser limitation prevents the Flash Player from issuing any HTTP PUT methods or HTTP DELETE methods, so I use HTTP GET and HTTP POST to implement all of my commands to manage my resource. The Flex MXML code below illustrates two separate HTTPService data components (one for HTTP GET and one for HTTP POST):

<fx:Declarations>     <mx:HTTPService id="getBooks" method="GET"     result="getBooks_resultHandler(event)" resultFormat="e4x"     fault="getBooks_faultHandler(event)" /> <mx:HTTPService id="addOrUpdateBook" url="{myBaseUrl}"                 contentType="application/xml" resultFormat="e4x" method="POST" result="addOrUpdateBook_resultHandler(event)"     fault="addOrUpdateBook_faultHandler(event)"  /> </fx:Declarations>

Within any Flex data component, I specify event listeners for the result and fault events. If the HTTP request succeeds, the service dispatches the result event, and my result handler is invoked. If the HTTP request fails, the service dispatches the fault event, and my fault handler is invoked. Once my result handler is invoked, I start processing my VOs.

Revisiting VOs

To start de-serializing the XML data from the Web service, I need to create ActionScript VOs to match my ibator-generated POJOs on the server. In other words, the names of the public getters and setters of the members in the POJO must have the same names as public members in the ActionScript VO. Here is my ActionScript VO class:

public class Book { public var bookid:int = -1; public var author:String = null; public var title:String = null; }

Here is my POJO class:

public class Book implements Serializable { private Integer bookid; private String author; private String title; public Integer getBookid() { return bookid; } public void setBookid(Integer bookid) { this.bookid = bookid; } public String getAuthor() { return author; } public void setAuthor(String author) { this.author = author == null ? null : author.trim(); } public String getTitle() { return title; } public void setTitle(String title) { this.title = title == null ? null : title.trim(); } }

For the serialization process to work, the objects must have matching public members. As you see above, bookid, author, and title are defined in both objects. For every POJO Java source file, there should be a VO ActionScript source file.

De-serializing XML into a VO

Now, I have developed all of my VOs. I can start the de-serialization from XML into VOs. Inside my result handler of the getBooks component, I start the process of de-serializing the resulting XML. Here is my ActionScript example code to illustrate:

var i:int = 0; var resp:XML = (event.result as XML); var count:int = resp.children().length();              if (count > 0) { model.bookModel.clearList(); } for (i=0; i<count; i++) { var rec:Object = resp.Book[i]; if (rec != null) { var book:Book = new Book(); book.deserialize(rec); model.bookModel.addBook(book); } }

In the code above, I store all of my VOs in my model, so I can easily bind them to any Flex UI component.

Serializing VO to XML

Now, say the user has made changes to an existing VO or wants to add a new VO. First, I need to serialize the VO into XML, and then pass the XML as a parameter to my RESTful data service for storage. In the code below, I am serializing the VO into XML for transportation to my service:

public function serialize():XML { var qName:QName = new QName("app.vo.Book");          var xmlDocument:XMLDocument = new XMLDocument(); var encoder:SimpleXMLEncoder = new SimpleXMLEncoder(xmlDocument); var xmlNode:XMLNode = encoder.encodeValue(this, qName, xmlDocument);          var xml:XML = new XML(xmlDocument.toString());         return xml; }

The user clicks Save, and my event listener starts the process of saving my book VO. I pass the serialized book VO as a parameter to my send request. Here is my ActionScript example code:

protected function saveBtn_clickHandler( event:MouseEvent):void { // updating if (selectedBook != null) {     pendingUpdate = new Book();     pendingUpdate.bookid = selectedBook.bookid;     pendingUpdate.title = titleText.text;     pendingUpdate.author = authorText.text; addOrUpdateBook.send(pendingUpdate.serialize());     } // adding new record     else {     pendingUpdate = new Book();     pendingUpdate.bookid = -1;     pendingUpdate.title = titleText.text;     pendingUpdate.author = authorText.text;     addOrUpdateBook.send(pendingUpdate.serialize());     } }

When the server responds to my request, I update my model. Once the VO is updated in the model, I can bind it to any view in my application, as shown in Figure 4.

Figure 4. Binding my VO to an application.

Conclusion

By combining a few server technologies, I can create a lightweight enterprise data service infrastructure that has the flexibility to support a more advanced application design for my Flex application. iBATIS provides me with a quick and simple API to my database without writing any Java code. Jersey REST provides a simple HTTP interface to my Web service without a lot of configuration. Spring glues all of the server technologies together, at the same time giving me some important server functionality to support a more advanced application design in the future. Flex's data components provide an easy mechanism for integrating with my RESTful data service. Hopefully, this infrastructure will allow you to focus on your application's look and feel to create more elaborate and elegant Flex applications.


Comment and Contribute

 

 

 

 

 


(Maximum characters: 1200). You have 1200 characters left.

 

 

Sitemap