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
Created directory gwtTable\src\javabeat\net
Created directory gwtTable\src\javabeat\net
Created file gwtTable\src\javabeat\net
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; } }
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 <code>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 has
to be used), for this and for its popularity it seemed important to
us to mention it in the article.
As it is illustrated in Figure
6, 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
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); } }
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
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.






May 25, 2007
AJAX, Web Frameworks