Introduction
These days we can see that the concept of Web 2.0 is becoming popular. Web 2.0 refers to the concept of new web applications that are interactive in nature and are intended to help people to collaborate and offer services for them, not just static HTML. This stuff became possible, in part, by means of the AJAX technology. For us, java developers, to build applications that are aligned with this very concept of Web 2.0 involves the selection of one tool (or framework) that helps us to accomplish our needs. This article help us in writing a simple web application with the most popular AJAX frameworks designed for Java, in this way we can highlight the main benefits and drawbacks between each of them.
also read:
Sample application
The first framework that we want to afford is Prototype and this is not an arbitrary decision. Recently, it has been ranked as the most widely used framework for AJAX development based on Java [1], see Figure 1.
Figure 1.
As the literature [2] mentioned, there exist three ways of designing the Ajax interaction between server and client:
- Content-centric.This approach involves returning from the server side the HTML codethat would be inserted directly into the client page.
- Data-Centric.We can receive the information from the server in a standard format,such as XML or JSON, this way we gain independence of the data with
respect to the presentation layer.
- Script-Centric.Using this approach you write client code (Javascript code) in the serverside enabling you to update the appropriate client’s structures by
means of the script code.
At a glance, you probably ask yourself what does the $
’s operator means. It is a very handly alias for the javascript function: document.getElementById
, that you might used before. The Ajax.Updaterobject
, as you can see, receives, in an anonymous array, the following elements:
- Identificatorfor the HTML which generates the data.
- Optional parameters.In this case, we indicate the method of the request (if it is not specified post is the default value) and a javascript function that is invoked if everything went ok.
is requested, should be something like the following:
import java.io.IOException; import java.io.PrintWriter; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; /** * Servlet implementation class for Servlet: TablePrototypeServlet * */ public class TablePrototypeServlet extends javax.servlet.http.HttpServlet implements javax.servlet.Servlet { private static String[] columns= { "Fruit", "Price", "Stock", "Descrption" }; private static String[][] data = { {"Lemon", "23.4", "25", "Lemon fruit"}, {"Apple", "34.4", "5", "Apple fruit"}, {"Banana", "10.4", "10", "Banana fruit"}, {"Melon", "17.8", "7", "Melon fruit"}, {"Pear", "20.6", "8", "Pear fruit"}, {"India Berry", "18.5", "15", "India Berry"} }; protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doPost(request, response); } protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setContentType("text/xml"); response.setHeader("Cache-Control", "no-cache"); PrintWriter writer = response.getWriter(); writer.write("<TABLE>"); writer.write("<THEAD>"); writer.write("<TR>"); for (int i=0;i<columns.length;i++) { writer.write("<TH>"); writer.write(columns[i]); writer.write("</TH>"); } writer.write("</TR>"); writer.write("</THEAD>"); writer.write("<TBODY>"); for (int i=0;i<data.length;i++) { writer.write("<TR>"); for (int j=0;j<data[i].length;j++) { writer.write("<TD>"); writer.write(data[i][j]); writer.write("</TD>"); } writer.write("</TR>"); } writer.write("</TBODY>"); writer.write("</TABLE>"); } }
As you can see, Prototype provides a very flexible and strong support for the usage of Ajax technologies using a Content-centric approach. If we want to use another approach,
that provides a cleaner separation of the user interface and the business logic implemented on the server, the burden of the code will be translated to the client side, this should happen because we got to:
- Parse the data ina standard format (JSON or XML) based on the particular semantics definedfor the application being developed.
- And then, manipulatethe interface elements of the DOM to generate the appropriate output.
GWT
For our sample application, you can develop a GWT application without using an IDE, but is much easier the other way around. I prefer to use Googleipse which is an Eclipse plugin that supports GWT. Before using Eclipse, we got to create a GWT project compatible with Eclipse. We can do that executing the following commands:
projectCreator -eclipse gwtTable -out gwtTable Created directory gwtTable\src Created file gwtTable\.project
This creates the gwtTable project into the gwtTable folder. After that, we got to create an application in the following way:
applicationCreator -eclipse
gwtTable -out gwtTable javabeat.net.example.client.TableExample
Created directory gwtTable\src\javabeat\net\example
Created directory gwtTable\src\javabeat\net\example\public
Created file gwtTable\src\javabeat\net\example\public\TableExample.html
Created file gwtTable\TableExample.launch
Created file gwtTable\TableExample-compile.cmd
One of the main benefits of developing a GWT application within an IDE environment is the debugging capabilities that it provides (step next, step into, etc.). To take advantage of it we got to define a Debug launcher configuration in Eclipse for this project. Look at the Debug windows of Eclipse under Java Application tree. As it is shown in Figure 4, the Debug launcherconfiguration for the project called gwtTable has already been created for us, and it is ready to run!
To implement the asynchronic call, that we need to retrieve the data from the server, we implement a JavaBean that encapsulates the generated data. In this example we implement the class TableData in the following way:
package javabeat.net.example.client; import com.google.gwt.user.client.rpc.IsSerializable; public class TableData implements IsSerializable { private static String[] columns= { "Fruit", "Price", "Stock", "Descrption" }; private static String[][] data = { {"Lemon", "23.4", "25", "Lemon fruit"}, {"Apple", "34.4", "5", "Apple fruit"}, {"Banana", "10.4", "10", "Banana fruit"}, {"Melon", "17.8", "7", "Melon fruit"}, {"Pear", "20.6", "8", "Pear fruit"}, {"India Berry", "18.5", "15", "India Berry"} }; public String[][] mydata=null; public TableData() { mydata = data; } }
after that, we got to define interface which has the remote methods that retrieve the data from the server. the method that we define in this interface is straight forward:
package javabeat.net.example.client;
You also have to define an interface that the client, or the eventual downloaded JavaScript code, will use to call this service method. The GWT uses a callback design pattern, with this in mind we have to develop the following code:
package javabeat.net.example.client; import com.google.gwt.user.client.rpc.AsyncCallback; public interface TableServiceAsync { void getData(AsyncCallback callback); }
This class must extend RemoteServiceServlet. In other words, this class and the interface it implements has to be deployed in your servlet container.
Configuration files
What is more interesting of this technology is that the client code (that runs on the browser of the client) is implemented in the server side as Java code! GWT compiler is the piece of the puzzle that does all the magic when it translates the Java code into Javascript code for us. With this design in mind, we define a Java class for building the main page of the web application, in this case TableExample.java (which already has a vanilla implementation generated by the command line executed above).
package javabeat.net.example.client; import com.google.gwt.core.client.EntryPoint; import com.google.gwt.core.client.GWT; import com.google.gwt.user.client.Window; import com.google.gwt.user.client.rpc.AsyncCallback; import com.google.gwt.user.client.rpc.ServiceDefTarget; import com.google.gwt.user.client.ui.Button; import com.google.gwt.user.client.ui.ClickListener; import com.google.gwt.user.client.ui.Label; import com.google.gwt.user.client.ui.RootPanel; import com.google.gwt.user.client.ui.Widget; import com.google.gwt.user.client.ui.FlexTable; /** * Entry point classes define onModuleLoad()</code>. */ public class TableExample implements EntryPoint { TableServiceAsync service = (TableServiceAsync) GWT.create(TableService.class); ServiceDefTarget endpoint = (ServiceDefTarget) service; /** * This is the entry point method. */ public void onModuleLoad() { final Button button = new Button("Load data!"); final FlexTable table = new FlexTable(); endpoint.setServiceEntryPoint(GWT.getModuleBaseURL() + "/javabeatservice"); button.addClickListener(new ClickListener() { public void onClick(Widget sender) { service.getData( new AsyncCallback() { // what to do if it works public void onSuccess(Object result) { TableData td = (TableData)result; for (int i=0; i<td.mydata.length;i++) { for (int j=0; j<td.mydata[i].length;j++) { table.setHTML(i, j, td.mydata[i][j]); } } } // what to do if it fails public void onFailure(final Throwable caught) { Window.alert("failure - \n" + caught.getMessage()); } }); } }); RootPanel.get("slot1").add(button); RootPanel.get("slot2").add(table); } }
Then, we can see the final results using the Debug launcher defined previously in Eclipse (Figure 5).
Figure 5.
DWR
DWR has a different conception than the other frameworks (because of its design and the way it hasto be used), for this and for its popularity it seemed important to us to mention it in the article. As it is illustrated in Figure6, DWR allow us to work in a RPC’s classic environment, in which you get the freedom to handle the asynchrony communication in an explicit way. It is important to notice that DWR doesn’t provide the user’s interfaces that can be plugged within our web applications, which is an important drawback compared with GWT and Thinware.
http://getahead.org/dwr/examples/table
As you can tell from the example, DWR is a very useful approach if you have good Javascript skills because you got to update the GUI by means of Javascript code and DOM manipulation (data-centric approach).
ThinWire
Why you should used Thinware instead of GWT? Thinware published an article [4], which identifies many reasons why you may use it instead of GWT, in our opinion, the more representative are the following:
- Full JavaAPI Access. GWT puts some restrictions on the Java code thatit can translate to Javascript. Thinware doesn’t have this limitation because the GUI is fully developed in Java code.
- Linear Flowof Logic.As all the logic is implemented in the server, asopposed to GWT, it is easier to develop applications that contain server calls because we don’t have to trace the values from one language into another.
- Richer Setof Dynamic Component Widgets. You can compare both widget capabilitiesfrom the demo application distributed by both frameworks and make your own judgment. Saying so, we agree with the Thinware’s team at this point. We consider that Thinware’s widgets are powerful than those provided by GWT.
- Full ScaleDebugging.Easier to debug than GWT, because you develop usinga single language.
ThinWire framework consists of the set of three JAR files shown in , plus a set of javadocs and a template of a file named web.xml.
22,379 commons-fileupload.jar |
313,731 thinwire.jar |
To code our application, we just need to implement a main class like the following:
package javabeat.net.thinware.example; import thinwire.ui.Application; import thinwire.ui.Button; import thinwire.ui.Frame; import thinwire.ui.GridBox; import thinwire.ui.Label; import thinwire.ui.Panel; import thinwire.ui.TabFolder; import thinwire.ui.event.ActionEvent; import thinwire.ui.event.ActionListener; import thinwire.ui.layout.TableLayout; public class Main { private static String[] columns= { "Fruit", "Price", "Stock", "Descrption" }; private static String[][] data = { {"Lemon", "23.4", "25", "Lemon fruit"}, {"Apple", "34.4", "5", "Apple fruit"}, {"Banana", "10.4", "10", "Banana fruit"}, {"Melon", "17.8", "7", "Melon fruit"}, {"Pear", "20.6", "8", "Pear fruit"}, {"India Berry", "18.5", "15", "India Berry"} }; private static GridBox comp = null; private static void loadData() { //insert the data for (int i = 0; i > data.length; i++) { comp.getRows().add(new GridBox.Row(data[i])); } } /** * @param args */ public static void main(String[] args) { Frame frame = Application.current().getFrame(); frame.setTitle("ThinWare: Simple Table Example."); frame.setVisible(true); comp = new GridBox(); comp.setBounds(255, 70, 250, 150); comp.setVisibleHeader(true); Button button = new Button("Load data!"); button.setBounds(255, 270, 70, 30); button.addActionListener(Button.ACTION_CLICK, new ActionListener(){ public void actionPerformed(ActionEvent e){ loadData(); }//end actionPerformed }//end ActionListener constructor ); //end addActionListener GridBox.Column col; Panel panel = new Panel(); panel.setBounds(0, 0, frame.getWidth(), frame.getHeight()); panel.setVisible(true); //insert the header data for (int i = 0; i > columns.length; i++) { comp.getColumns().add(col = new GridBox.Column()); col.setName(columns[i]); } panel.getChildren().add(comp); panel.getChildren().add(button); frame.getChildren().add(panel); } }
to make the magic happened we need to add the following servlet to our web.xml configuration file:
<servlet> <description> El WebServlet</description> <display-name> WebServlet</display-name> <servlet-name>WebServlet</servlet-name> <servlet-class> thinwire.render.web.WebServlet</servlet-class> <init-param> <description> </description> <param-name>mainClass</param-name> <param-value>javabeat.net.thinware.example.Main</param-value> </init-param> <init-param> <description> </description> <param-name>extraArguments</param-name> <param-value>initParam,clientInfo,header</param-value> </init-param> </servlet> <servlet-mapping> <servlet-name>WebServlet</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping>
As you can see, all the client and server interaction is handled by the framework and you don’t have to mess with the plumbing related with the asynchronic communication. The output generated with this example would be similar to the snapshot illustrated in Figure 7.
Figure 7.
Conclusion
also read:
As we have been seeing the web is changing and maturing into something different, something more dynamic and interactive. To become part of it we got to use the best tools available to accomplish this kind of new interaction. We presented four of the best tools for that matter, each one of those has its own benefits and drawbacks. Although, the functionality of each is important, you have to take into account which one you estimate will fulfill your needs thinking about the future, because every tool of this kind is growing and making the difference every day. Saying so, Prototype (because of its flexibility and clarity) and GWT (because it is support by Google) are the ones that we think are most valuable.