ZK vs. GWT : Server-Centric Matters!

Jeff Liu, Engineer, Potix Corporation
February 18, 2008

Contents

  1. Abstract
  2. Server-Centric and Client-Centric
  3. ZK vs. GWT in Action : Google Maps Locator
  4. ZK vs. GWT in Action 2 : Data-binding
  5. ZK vs. GWT in Action 3 : Live data
  6. ZK Anywhere
  7. Conclusion

1. Abstract

On Feb 18th, 2005 Jesse James Garrett first introduced the term “AJAX” in his essay “Ajax: A New Approach to Web Applications.” Since then, Ajax has become a very popular topic in web application development communities. In the past 2 years, numerous Ajax frameworks have been built for the development community. These frameworks vary from pure JavaScript frameworks, such as Yahoo! UI (YUI), to Flash based ones such as Adobe’s AIR (Adobe Integrated Runtime). But, one important concept is often ignored by the media and general audience: are the frameworks server-centric or client-centric? This article attempts to clarify some misconception with real ZK and GWT examples.

2. Server-Centric and Client-Centric

Where Applications Run:

In short, the main difference between server-centric and client-centric is where the application runs. In a server-centric framework, the application is hosted on the application server and all processing is done on the server. The client browser is only used for data presentation.

In contrast, applications that do all of their processing on the client side, such as GWT, use JavaScript running in the client browser.


 

Figure 1 - Server-Centric vs. Client-Centric

 

Server and Client Centric Ajax Frameworks in Practice:  ZK and GWT

ZK and GWT bring a similar mantra to Java developers - developing Ajax applications using Java rather than JavaScript. To developers who rely on Java as their tool of choice, both frameworks offer a great escape from the JavaScript nightmare.

At the first glance, developers will consider that these 2 frameworks are similar: both allow the developer to use Java, and they both, support AJAX user interface components. Probe a little more deeply into the mechanism behind both frameworks and you will see that ZK and GWT work in an entirely different fashion. Generally GWT compiles Java code into JavaScript allowing the application to run in the client’s browser rather than on the server's. Applications built of GWT interact with the server only when data retrieval is necessary. ZK framework uses a different approach from GWT: the application runs on the server and ZK takes care of the presentation layer.


To Know more how ZK works as a server-centric framework, refer to the following:

3. ZK vs. GWT in Action : Google Maps Locator

In the following section a simple Google Maps Locator application will be implemented by ZK and GWT in order to demonstrate the difference between the frameworks.  Assuming that you are coding a Google Maps Locator for a client, the  requirements might contain:

  1. An UI with a text input field, a button and a Google map.
  2. When user clicks the button the text in the textbox will be used as a keyword to find the latitude, longitude and description for that location.
  3. Displaying the location on the Google Map and display the description as an Info Window.

Figure.2 - Google Maps Locator

Let us assume you have already implemented a magical Java class which is called “Locator.” It will take a string as input and return the required information.  The only work left is implementing the UI and data retrieval parts.  Let’s see code from both frameworks in real action.

ZK (1 File, 36 Lines of Code)

Gmap.zul:

	
<?xml version="1.0" encoding="utf-8"?>
<zk>  
      <script src="http://maps.google.com/maps?file=api&amp;v=2&amp;key=KEY"
      type="text/javascript">
      </script>
      <zscript>
           import com.macroselfian.gps.Locator;
           public void locate(){
               String location = tb.getValue();
               double[] pos = Locator.locate(location);
               mymap.panTo(pos[0], pos[1]);
               mymap.setZoom(16); 
               ginfo.setOpen(true);
               ginfo.setLat(pos[0]);
               ginfo.setLng(pos[1]);
               ginfo.setContent(Locator.getInfo(location));
               mymap.openInfo(ginfo); 
           }
      </zscript>
      <window>
           <div align="center">
               <separator spacing="50px" />
               <vbox>
                    <label value="Macroselfian Google Map Locator"/>
                    <hbox width="600px">
                        <textbox width="550px" id="tb"/>
                        <button width="50px" onClick="locate();" label="Search"/>
                    </hbox>
                    <gmaps id="mymap" zoom="16" ...>
                        <ginfo id="ginfo"/>
                    </gmaps>
               </vbox>
           </div>
      </window>
</zk>
	

GWT (5 Files, 190 Lines of Code)

Client Side Files:

  1. Map.java – The main application class
  2. LocationGenerator.java – The interface for RPC.
  3. LocationGeneratorAsync.java- The interface for RPC.
  4. LocatorData.java – The data wrapper class for passing data from server.

Server Side Files:

  1. LocationGeneratorImpl.java – The data provider class in server side.

Code Snippet:

Map.java:

	
…
public class Map implements EntryPoint {
      …     
      public void onModuleLoad() {
      …
      mapWidget = new GMap2Widget("400", "600");
			  gmaps = mapWidget.getGmap();
			  gmaps.addControl(GControl.GMapTypeControl());
			  gmaps.addControl(GControl.GLargeMapControl());
			  gmaps.setZoom(16);
			  VerticalPanel vPanel = new VerticalPanel();
			  HorizontalPanel hPanel = new HorizontalPanel();
			  hPanel.add(location);
			  hPanel.add(search);
			  vPanel.add(title);
      vPanel.add(hPanel);
      vPanel.add(mapWidget);   
      RootPanel.get().add(vPanel);
      }
 
      public class ClickListenerImpl implements ClickListener{
           public void onClick(Widget widget) {
               LocationGeneratorAsync async = 
             LocationGenerator.Util.getInstance();
               async.locate(location.getText(), new LocationCallback());
           }
      }
 
      public class LocationCallback implements AsyncCallback {
           public void onFailure(Throwable error) {
               response.setText("Ops..!");
           }
 
           public void onSuccess(Object resp) {
               LocatorData data = (LocatorData)resp;
               double lat = data.getLat();
               double lng= data.getLng();
               String inf = data.getInfo();
               Label info = new Label(inf);
               info.setStyleName("map-info");
          GLatLng pos = new GLatLng(lat,lng);
          gmaps.setCenter(pos);
          gmaps.openInfoWindow(pos,info);
      }
  }
}

	

LocationGenerator.java:

	
public interface LocationGenerator extends RemoteService {
	public static final String SERVICE_URI = "/locationgenerator";
	      public static class Util {
	           public static LocationGeneratorAsync getInstance() {
	               LocationGeneratorAsync instance =  
	       (LocationGeneratorAsync)GWT.create(LocationGenerator.class);
	               ServiceDefTarget target = (ServiceDefTarget) instance;
	               target.setServiceEntryPoint(GWT.getModuleBaseURL()SERVICE_URI);
	               return instance;
	           }
	      }
      public LocatorData locate(String location);
}
	

LocationGeneratorAsync.java:

	
public interface LocationGeneratorAsync {
    public void locate(String location, AsyncCallback callback);
}
	

LocatorData.java:

	
public class LocatorData implements IsSerializable {
    private double _lng;
    private double _lat;
    private String _info;
    private String _title;
      
    public LocatorData(double lat, double lng, String info,…) {
         _lng = lng;
         _lat = lat;
         _info = info;
         _title = title;
    }
      …
}
	

LocationGeneraotrImpl.java:

	
public class LocationGeneratorImpl extends RemoteServiceServlet implements LocationGenerator {
    public LocatorData locate(String location) {
       com.macroselfian.gps.Locator locator = 
       new com.macroselfian.gps.Locator(location);
       LocatorData data = new 
       LocatorData(locator.getLat(),locator.getLng(),locator.getInfo(), 
       locator.getTitle());
       return data;
    }
}

	

Using the ZK framework, the component’s state is maintained by the server. One of the advantages of server-centric applications is that data retrieval and business logic processing are straight-forward. Since the component states are maintained on the server side, retrieving data or processing business logic requests require no extra work.

In contrast, a GWT-RPC call is required when GWT applications needs data from the server. In Map.java, async.locate(…) is called when onClick is trigged, then a callback object, LocationCallback is required to process the returned data. If you have any JavaScript programming experience, you will soon find out that it is very similar to calling XMLHttpRequest functions in JavaScript. Up to this point you have probably figured out that by using ZK’s server-centric approach, developers don’t have to make an RPC call and handle the returned data manually.

DWR (2 Files, 77 Lines of Code)

Here is a sample code for achieve the same functionality by another client-centric framework, DWR.

Web.xml

	
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee
 http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
    <servlet>
       <servlet-name>dwr-invoker</servlet-name>
       <servlet-class>
         org.directwebremoting.servlet.DwrServlet
       </servlet-class>
       <init-param>
         <param-name>debug</param-name>
         <param-value>true</param-value>
       </init-param>
    </servlet>
    <servlet-mapping>
       <servlet-name>dwr-invoker</servlet-name>
       <url-pattern>/dwr/*</url-pattern>
    </servlet-mapping>
</web-app>
	

Map.htm

	
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
  <script type="text/javascript" src="dwr/engine.js"></script>
  <script type="text/javascript" src="dwr/util.js"></script>
  <script type='text/javascript' src='dwr/interface/locator.js'> </script>
  <script src="http://maps.google.com/maps?file=api&amp;v=2" type="text/javascript"></script>
  <script type="text/javascript" src="http://www.google.com/jsapi?key=ABCDEFG"></script>
</head>
<body>
<script language="javascript" >
 
      var lng, lat, map;
 
      function goto(location){
          locator.locate(location, callBackLat);
      }
      
      function callBackLat(data){
           lat = data[0];
           lng = data[1];
          load();
       }
       
      function load(){
        if (GBrowserIsCompatible()) {
          var level = 16;
          map = new GMap2(document.getElementById("map_canvas"));
          map.setCenter(new GLatLng(lat, lng), level);
          map.addControl(new GSmallMapControl());
      map.addControl(new GMapTypeControl());
          var point = new GLatLng(lat,lng);
          setGmarker();
          setGinfo();
        }
       }
      
      function setGmarker(){
           var point = new GLatLng(lat,lng);
           map.addOverlay(new GMarker(point));
      }
      
      function setGinfo(){
           locator.getInfo(location, callBackGinfo);
      }
      
      function callBackGinfo(data){
           var point = new GLatLng(lat,lng);
           span_element = document.createElement("span");
           span_element.setAttribute("style","font-size:11px;font-family:verdana;");
           txt_node = document.createTextNode(data);
           span_element.appendChild(txt_node);
           map.openInfoWindow(point,span_element);
      }
 
</script>
<input id="location" type="textbox" onchange="goto(this.value);" />
<div id="map_canvas" style="width: 500px; height: 300px"></div>
</body>
</html>

	

Both GWT and DWR use the client-centric approach, but DWR is quite different from GWT. Compared to GWT, DWR requires less codes. However, as a result of its flexibility, developers have to handle the browser dependency issues. In short, DWR only builds the “bridge” between the client and the server.

4. ZK vs. GWT in Action 2 : Data-binding

Every developer will encounter this in his/her career, displaying master and detail problem. For example, there is list of names when the user clicks on one of names; the details behind the name need to be displayed in the details panel. ZK comes with a very neat solution for this task: annotation data-binding. For more information about ZK annotation data-binding, please refer to Y-Grid Support Drag-Drop and DataBinding.

To achieve this task in GWT, developers need to make an RPC call, find which cell in the grid which needs updating and so on. It is not a bad idea, but you have to do all that work by yourself.

ZK (1 File, 39 Lines of Code)

ygrid-databinding2.zul

	
<?init class="org.zkforge.yuiext.zkplus.databind.AnnotateDataBinderInit" ?> 
<window xmlns:y="http://www.zkoss.org/2007/yui" width="500px">
    <zscript src="Person.zs"/>
    <y:grid height="200px" model="@{persons}" selectedItem="@{selected}">
       <y:columns>
         <y:column label="First Name"/>
         <y:column label="Last Name"/>
         <y:column label="Full Name"/>
       </y:columns>
       <y:rows>
      <y:row self="@{each=person}">
      <y:label value="@{person.firstName}"/>
      <y:label value="@{person.lastName}"/>
      <y:label value="@{person.fullName}"/>
         </y:row>
       </y:rows>
    </y:grid>
  <!-- show the detail of the selected person -->   
  <textbox value="@{selected.firstName}"/>
  <textbox  value="@{selected.lastName}"/>
  <label  value="@{selected.fullName}"/>
  <zscript>
       //init each person
       setupPerson(Person person, int j) {
	       person.setFirstName("First "+j);
	       person.setLastName("Last "+j);
       }  
       //prepare the example persons List
       int count = 30;
       List persons = new ArrayList();
       for(int j= 0; j &lt; count; ++j) {
       Person personx = new Person();
       if(j==0)
			selected = personx;
       setupPerson(personx, j);
       persons.add(personx);
       }  
  </zscript>
</window>

	

GWT (4 Files, 200 Lines of code)

Client Side Code:

  1. FooExt.java – The main application class
  2. DataSourceGenerator.java – The interface for RPC.
  3. DataSourceGeneratorAsync.java- The interface for RPC.

Server Side Code:

  1. DataSourceGeneratorImpl.java – The actual data provider class in server side.

Code Snippet:

FooExt.java:

	
package test.gwtExt.client;
import com.google.gwt.core.client.EntryPoint;
…
public class FooExt implements EntryPoint {
    
    …
    
    public void onModuleLoad() {
       _response = new Label();
       _first = new TextBox();
       _first.setName("first");
       _first.addChangeListener(new OnTextChangeListenerImpl());
       _last = new TextBox();
       _last.setName("last");
       _last.addChangeListener(new OnTextChangeListenerImpl());
       DataSourceGeneratorAsync async = 
         DataSourceGenerator.Util.getInstance();
       async.getData(new DataCallback());
       RootPanel.get().add(_first);
       RootPanel.get().add(_last);
       RootPanel.get().add(_response);
    }
    
    public class DataCallback implements AsyncCallback {
 
    public void onFailure(Throwable error) {
         …     
  }
 
  public void onSuccess(Object resp) {
    Object[][] data = (Object[][])resp;
    createGrid(data);
  }
  }
    
    public void createGrid(Object[][] data){
          
       MemoryProxy proxy = new MemoryProxy(data);
       _recordDef =  new RecordDef(
         new FieldDef[]{
          new StringFieldDef("first"),
          new StringFieldDef("last"),
          new StringFieldDef("full")
         }
       );
         
       ArrayReader reader = new ArrayReader(_recordDef);  
 
       Store store = new Store(proxy, reader);
       store.load();
       ColumnModel columnModel = new ColumnModel(new ColumnConfig[]{
         new ColumnConfig() {
          {
            setHeader("First Name");
            setWidth(160);
            setSortable(true);
            setLocked(false);
            setDataIndex("first");
          }
         },
         new ColumnConfig() {
          {
            setHeader("Last Name");
            setWidth(100);
            setSortable(true);
            setDataIndex("last");
          }
         },
         new ColumnConfig(){
          {
            setHeader("Full Name");
            setWidth(260);
            setRenderer(new Renderer(){
                public String render(…);
 
       _grid = new Grid("grid-example1", "460px", "300px", store, …);
       _grid.addGridRowListener(new RowClickListener());
       _grid.render();
 
    }
    
    public class RowClickListener implements GridRowListener{
 
       public void onRowClick(Grid grid, int rowIndex, EventObject e) {
         FieldDef[] fs = _recordDef.getFields();
         Record record = grid.getStore().getAt(rowIndex);
         _first.setText(record.getAsString(fs[0].getName()));
         _last.setText(record.getAsString(fs[1].getName()));
         _selectedRow = rowIndex;
       }
 
       …
       
    }
    
     public class OnTextChangeListenerImpl implements ChangeListener {
       public void onChange(Widget widget) {
         /*
          * TODO: Modify data in server side by RPC
          */
         TextBox target = (TextBox)widget;
         Record r = _grid.getStore().getAt(_selectedRow);
         if(target.getName().equals("first")){
          r.set("first", target.getText());
         }else if(target.getName().equals("last")){
          r.set("last",target.getText());
         }
       }
    }
}

	

DataSourceGenerator.java:

	
public interface DataSourceGenerator extends RemoteService {
    public static final String SERVICE_URI = "/datasourcegenerator";
    public static class Util {
       public static DataSourceGeneratorAsync getInstance() {
         DataSourceGeneratorAsync instance = 
         (DataSourceGeneratorAsync)GWT.create(DataSourceGenerator.class);
         ServiceDefTarget target = (ServiceDefTarget) instance;
         target.setServiceEntryPoint(GWT.getModuleBaseURL() + SERVICE_URI);
         return instance;
       }
    }
    public String[][] getData();  
}

	

DataSourceGeneratorAsync.java:

	
public interface DataSourceGeneratorAsync {
    public void getData(AsyncCallback callback);
}

	

DataSourceGeneratorImpl.java:

	
public class DataSourceGeneratorImpl extends RemoteServiceServlet implements DataSourceGenerator {
    public String[][] getData() {
       org.zkoss.demo.DataSource ds = new org.zkoss.demo.DataSource();
       return ds.getData();
    }
}
	

 

5. ZK vs. GWT in Action 3 : Live data

One of the most frustrating problems for web application developers is displaying large amounts of data without the latency of data loading. ZK comes out with a very neat solution to this problem, live data (load-on-demand). For more information about ZK live data, refer to How to realize the idea of live data in a Grid.

ZK (1 File, 15 Lines of Code)

Ygrid-livedata.zul:

	
<window xmlns:y="http://www.zkoss.org/2007/yui" title="Y-Grid Live Data"  width="200px"  border="normal">
    <zscript><![CDATA[
       String[] data = new String[200];
       for(int j=0; j < data.length; ++j) {
       data[j] = "option "+j;
    } 
    ListModel strset = new SimpleListModel(data);
    ]]></zscript>
    <y:grid height="200px" model="${strset}">
       <y:columns>
         <y:column label="options"/>
       </y:columns>
    </y:grid>
</window>
	

GWT (I Don’t Ever Want to Code It)

The concept is like this: add a listener for the grid’s bodyscroll event then, when the body is scrolled, get the “proper” data from server by GWT-RPC. After that parse the data and add the data into the grid’s model and then finally, call the grid’s render method. If you know a better way to accomplish this task, please contact me.

6. ZK Anywhere

What about the devices without browsers?

Due to the iPhone phenomenon, some Ajax solutions support smart phones with browsers. But, what about 1.8 billion Java phones which do not come with such resources (computing power, memory, browser, etc.) that iPhone provides? The server-centric/thin-client approach by ZK brings benefits to those resource constrained devices. Your client devices will not be limited to robust ones with browser. With ZK, you can run your Web applications anywhere.

ZK on Java Phones

Figure 3 - ZK on Java Phone

More articles about ZK Mobile

ZK on Google Adroid

Figure 4 - ZK on Android

More aritcles about ZK Android

7. Conclusion

Right Tool for the Right Job

In the process of collecting information for this article, I found out that there are thousands of articles comparing Ajax frameworks. Many of them are trying to convince the reader that one framework is a “better” choice than others, thus treating the Ajax framework market as a Zero-Sum Game. I personally see it from a different point of view. After having seen both the server-centric and client-centric frameworks, making a comparison for them is like comparing apples to oranges. Both frameworks come with the initiative of developing Ajax applications with less efforts, but they take an entirely different approach to it.

To me, both of them are great tools to use. The real question is what kind of problem are you trying to solve?

Find the right tool for the right job. For heavy data access applications and projects that require a higher level of security, I prefer the server-centric approach. If the application requires fancy client side actions and less server requests, the client-centric approach could be my choice.

Comments
 
robertpic
2008-02-21

Good article. Maybe you should announce this in the news.

I will host the examples from the "Struts, JSF vs. ZK article" from the german Javamagazin. I do some improvements (i.e. databinding) for the ZK resolution.

The ZK resolution needs 40% less code than the JSF and 50% less code than the Struts example.

The example includes the description for the databindingconverters (i.e. boolean to image).
I get out of track and spend my time with JDBC-Binding (via converter) which works also nice....

I hope i am ready this week.

/Robert

Jim Yeh
2008-02-22

Robert,

Looking forward to your article!

Let us know when it's ready.

/Jim

Christophe Hanon
2008-02-22

Interesting article, but obviously the author is pro ZK.

GWT makes good job to develop Ajax Client Browser app shielded from Javascript and difference between (the supported) browser. Clearly GWT miss an application framework for databound application. That may come though. May be somebody has already done one? My major concern about GWT is this translation technology (Java -> Javascript), in theory it is nice, but in case of bugs in the framework that may hurt.

ZK shields the developer much more but on the other side, ZK server centric approach makes it a poor candidate for largely distributed apps. Handling component event at the server level introduce major slowness.

Also I don't see a word about the licensing, here ZK is a major trouble with the different versions and undeclared pricing for Enterprise version. I thinl a good framework should be LGPL. Commerical offering should go for training, certification, support,GUI builder etc

It would be great to have more comparison articles between all these frameworks (wicket, click, jsf etc).

So lets continue searching the perfect framework...

Christophe

Jebberwocky
2008-02-22

To Christophen Hanon

When the application developers by GWT, the "Web Service Approach" is often used. Since that GWT doesn't keep any objects(data or class) in server side, it will highly depended on the We Service to get its relevant data. For example, when you try to find a id from a person, you might get data from Web Service. And, the web service might go through every process which is needed. It sometimes results in hefty server loading too.

The "design" is the key point here. The design of your application and web service matters!

Marcos de Sousa
2008-02-22

Good article.

Why not publish it on www.theserverside.com and www.infoq.com ?

Marcos de Sousa

Zing
2008-02-22

This is an awesome article. ZK is probably the best AJAX framework out there - and it is certainly better than any of the non-AJAX frameworks such as JSF and Struts. Unfortunately, ZK does not get the same amount of press coverage as GWT. GWT is good, but it is NOT suitable for large applications. GWT is suitable for small applications with large (millions) of users. Also, GWT requires the developer to write a lot more code, and be aware of a lot more Javascript type concepts. ZK is definitely the most practical framework for large business applications with small to medium (less than 100,000) number of users. ZK takes the easiest concepts of web and desktop Java application development, and combines them into an awesome web framework.

Ricardo M. Augusto
2008-02-23

Hi,

I have implemented this "magical" Java class which is called "Locator" with a GMapsLocator project.
GMapsLocator uses GClientGeocoder to translate an address in coordinate, or
in many coordinates, it depends how precision was your address.

Get Latitude and Longitude and more from address and use with GMaps.

See a demo and download !
http://www.ecafe.com.br/locator/


GMapsLocator is open source and free for any use.
Problems or suggestions, please contact me.
ricardo@ecafe.com.br


Ricardo M. Augusto

Jeff Liu
2008-02-24

Ricardo. Great work !

Sean
2008-03-02

Isn't it better to provide an example that template does not have code?
For a trivial example, it looks fine, but it reminds me of JSP with <% code %>.
Is there any visual debugger that can trace the ZK script code in the page template?

Jeff Liu
2008-03-03

By MVC approach

gmap2.zul

<?xml version="1.0" encoding="utf-8"?>
<zk>
	<script
		src="http://maps.google.com/maps?file=api&v=2&key=ABQIAAAA_a5cKDw802_dX3vWdInYqhTIlznav5OIV7y4zT7agJRovS0PzhQ0UBGBbe2oqlCTDbp4fH0LER3l3g"
		type="text/javascript">
	</script>
<window apply="com.macroselfian.gps.MapComposer" >
		<vbox >
			<label value="Macroselfian Google Map Locator"/>
			<hbox width="610px">
				<textbox width="550px" id="tb"/>
				<button width="60px" forward="onLocate" label="Search"/>
			</hbox>
			<gmaps id="mymap" zoom="16" showTypeCtrl="true" showLargeCtrl="true" width="610px" height="400px">
				<ginfo id="ginfo"/>
			</gmaps>
		</vbox>
</window>
</zk>

MapComposer.java

package com.macroselfian.gps;

import org.zkoss.zk.ui.event.Event;
import org.zkoss.zk.ui.util.GenericComposer;
import org.zkoss.zul.Textbox;
import org.zkoss.zul.Window;
import org.zkoss.gmaps.Gmaps;
import org.zkoss.gmaps.Ginfo;


public class MapComposer extends GenericComposer {

	public void onLocate(Event evt){
		Window win = (Window)evt.getTarget();
		Textbox tb = (Textbox)win.getFellow("tb");
		Gmaps mymap = (Gmaps) win.getFellow("mymap");
		Ginfo ginfo = (Ginfo) win.getFellow("ginfo");
		String location = tb.getValue();
		Locator locator = new Locator(location);
		mymap.panTo(locator.getLat(), locator.getLng());
		mymap.setZoom(16); 
		ginfo.setOpen(true);
		ginfo.setLat(locator.getLat());
		ginfo.setLng(locator.getLng());
		ginfo.setContent(locator.getInfo());
		mymap.openInfo(ginfo); 
		
	}
}

Refer to http://www.zkoss.org/smalltalks/mvc/

Jeff Liu
2008-03-07

One of the things that ZK does that's different from all the other Web2.0 frameworks (Prototype, jQuery, YUI, etc) is that it puts the behavior code (control and model) back on the server: "In response to these challenges, ZK delivers the intuitive desktop programming model to Web applications with event-driven, component-based, and server-centric architecture" "It is aimed to bring the desktop programming model to Web applications." ~ Bill McDonald from ZK Forum

Prabakar
2008-03-26

I have 2 observations:
1) Though ZK uses XUL (or ZUML), it looks very much similar to the technique where people extend HTML tags (ex: Backbase). Can some one explain how ZK is different?
2) One of key issues with server centric approach is "debugging". Since the HTML page is generated on the fly, if any bugs are reported, it will be difficult to debug - especially when the developers code using only 'Java' & they may not know how their java code will be translated into HTML at runtime.

Jeff
2008-04-10

From ZK developer guide:

The ZK User Interface Markup Language (ZUML) is a XML-based language used by developers to describe the visual presentation. ZUML is aimed to separate the dependency of the set of components to use. In other words, different set of components[28], such as XUL and XHTML, could be used simultaneously in the same ZUML page. Different markup languages could be added transparently. If two or more set of components are used in the same page, developers have to use the XML namespaces to distinguish them. Refer to the Component Sets and XML Namespaces section in the ZK User Interface Markup Language chapter if you want to mix multiple component sets, say XUL and XHTML, in the same page.

Jeff
2008-04-10

I think that one of the ZK framework's goals is to prevent Java users from the HTML & JavaScript. In most of cases, ZK frameworks will take all the client side action, javascript events, HTML DOM-tree manipulation and etc. Developers should only worry about the Java doe. But, in some rare cases, accidents happen. In this situaion, there are some tools like Firebug, developer toolkit and so on for the debugging.

shinyr
2008-04-11

So,what's the difference between ZK and openlaszlo?

jeff
2008-04-14

First of all, there is a huge difference in client engines. ZK uses standard HTML, JavaScript , CSS and ... OpenLaszlo uses Flash.

Norio
2008-04-15

OpenLaszlo is good for animation (Flash) and more for art designers, but lack of integration with back end (programming in Java, data access, other Java frameworks).
In contrast, programming in Java and server-side integration are ZK's strengths.

Simon
2008-05-30

Christophen Hanon said:

> ZK server centric approach makes it a poor candidate for largely distributed apps.

However flipping that around one is saying "we can farm off the custom processing to the javascript engine in the clients browser". Even within a large company you cannot control exactly what browser versions and security settings the users are using. The browser javascript runtime of your users is simply out_of_our_control. In our tests our server side ZK events typically get processed in 10ms. As it is that fast on the server there really is nothing to be gained by trying to push custom javascript code out to the clients browser. By using ZK only well tested and widely used opensource library code is being sent to the browser which is the least risk for our rich webapp application.

Jorge
2008-05-30

I totally agree with this article, because I've tested both frameworks from scratch, GWT seemed quite more complex, particularly focusing the development of complex data access applications. On the other hand, GWT is much faster because of it's architecture, loads faster, renders faster, gave me a better user experience, specially running through a slow network connection. Zk has a richer set of components (GWT uses only DOM level 1) that really simplify developers labor. Keep in mind that we are in Google's era, this could be an important thing to take into account. I don't have metrics on server/client side resources usage, I'll appreciate if someone could send his/her conclusions on this matter.

Jeff liu
2008-06-05

Dear Jorge

Could you provide us the data from your testing result?
contact me at jeffliu@zkoss.org

HIBERNATOR
2008-06-09

GWT offers some nice UI widgets (from GWT-Ext especially), but GWT is definitely not ready for data driven applications. Search for "GWT hibernate CRUD demo" on your favorite search engine, and let me know how many links you find where you can download a working example!

Jeff
2008-06-10

To see how easy ZK works with Spring and Hibernate
http://www.zkoss.org/smalltalks/hibernatezk/hibernatezk.dsp
and
http://www.zkoss.org/smalltalks/hibnsprn/hibn_sprn_zk.html
Also, the outcoming zk forum is based on ZK+Spring+Hibernate

 
 
Leave a Reply
 
Name (required)
Mail (will not be published)(required)
Website
(Case Insensitive)
Bold textItalic textUnderLine textSource CodeHorizontal rulerExternal Link
SourceForge.net