DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Refcards Trend Reports
Events Video Library
Over 2 million developers have joined DZone. Join Today! Thanks for visiting DZone today,
Edit Profile Manage Email Subscriptions Moderation Admin Console How to Post to DZone Article Submission Guidelines
View Profile
Sign Out
Refcards
Trend Reports
Events
View Events Video Library
Zones
Culture and Methodologies Agile Career Development Methodologies Team Management
Data Engineering AI/ML Big Data Data Databases IoT
Software Design and Architecture Cloud Architecture Containers Integration Microservices Performance Security
Coding Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Culture and Methodologies
Agile Career Development Methodologies Team Management
Data Engineering
AI/ML Big Data Data Databases IoT
Software Design and Architecture
Cloud Architecture Containers Integration Microservices Performance Security
Coding
Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance
Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks

Integrating PostgreSQL Databases with ANF: Join this workshop to learn how to create a PostgreSQL server using Instaclustr’s managed service

Mobile Database Essentials: Assess data needs, storage requirements, and more when leveraging databases for cloud and edge applications.

Monitoring and Observability for LLMs: Datadog and Google Cloud discuss how to achieve optimal AI model performance.

Automated Testing: The latest on architecture, TDD, and the benefits of AI and low-code tools.

Related

  • Java 2021: What Frameworks and Trends for This New Year?
  • Code Generation in CUBA: What makes the magic
  • Modern Cloud-Native Jakarta EE Frameworks: Tips, Challenges, and Trends.
  • What Java DAO Layer Is Best for Your Project

Trending

  • How To Deploy Helidon Application to Kubernetes With Kubernetes Maven Plugin
  • API Design
  • Exploring Sorting Algorithms: A Comprehensive Guide
  • A Better Web3 Experience: Account Abstraction From Flow (Part 2)
  1. DZone
  2. Coding
  3. Frameworks
  4. Server Centric Java Frameworks: Performance Comparison

Server Centric Java Frameworks: Performance Comparison

Jose Maria Arranz user avatar by
Jose Maria Arranz
·
Sep. 07, 10 · Interview
Like (0)
Save
Tweet
Share
22.00K Views

Join the DZone community and get the full member experience.

Join For Free

These days we are used to AJAX-intensive, sophisticated web frameworks. These frameworks provide us desktop style development into the Single Page Interface (SPI) paradigm. As you know there are two main types of frameworks, client-centric and server-centric. Each approach has pros and cons.

Testing the performance of Java server-centric frameworks

In the server-centric view, state is managed in server.  In some way the client is a sophisticated terminal of the server because most of visual decisions are taken on the server and some kind of visual rendering is done on the server (HTML generation as markup or embedded in JavaScript or more higher level code sent to the client). The main advantage is that data and visual rendering are together in the same memory space, avoiding custom client-server bridges for data communication and synchronization, typical of the client-centric approach.

This article only reviews Java server-centric frameworks. 

In SPI, the web page is partially changed; that is, some HTML parts can be removed and some new HTML markup can be inserted. This approach obviously saves tons of bandwidth and computer power because the complete page is not rebuilt and not fully sent to the client when some page change happens.

A server-centric framework to be effective must send to the client ONLY the markup going to be changed or equivalent instructions in some form, when some AJAX event hits the server.

This article reviews how much effective most of the SPI Java web frameworks are on partial changes provided by the server. We are not interested in events with no server communication, that is, events with no (possible) server control.

How they are going to be measured

We are going to measure the amount of code that is sent to client regarding to the visual change performed in client.

For instance for a minor visual change (some new data) in a component we expect not much code from server, that is, the new markup needed as plain HTML, or embedded in JavaScript, or some high level instructions containing the new data to be visualized. Otherwise something seems wrong for instance the complete component or page zone is rebuilt, wasting bandwidth and client power (and maybe server power).

Because we will use public demos, we are not going to get a definitive and fine grain benchmark. But you will see very strong differences between frameworks.

The testing technique is very easy and everybody can do it with no special infrastructure, we just need FireFox and FireBug. In this test FireFox 3.6.8 and FireBug 1.5.4 are used.

The FireBug Console when "Show XMLHttpRequests" is enabled logs any AJAX request showing the server response.

The process is simple:

  1. The Console will be enabled before loading the page with the demo.
  2. Some clicks will drive some concrete component to the desired state.
  3. A final click will perform a small change in the component being analyzed.
  4. Then we will copy the output code of the AJAX request (HTML, XML, JavaScript ...) sent from server.

The more code the less effective, more bandwidth waste and client processing is needed.

We cannot measure the server power used because we need a deep knowledge of how the framework works in server, said this we can easily "suspect" the more code generated in server the more server power is wasted.

Frameworks tested

RichFaces, IceFaces,  MyFaces/Trinidad, OpenFaces, PrimeFaces, Vaadin, ZK, ItsNat

ADF Faces is not tested because there is no longer a public live demo. Because ADF Faces is based on Trinidad, Trinidad analysis could be extrapolated to ADF Faces (?).

Update: NO, ADF Faces are very different to Trinidad.

Note before starting

Some frameworks seem to perform very well (regarding to this kind of test), that is, the ratio between visual change and amount of code is acceptable, but in some concrete cases (components) they "miserably" fail. This article tries to measure bad performant components.

RichFaces

 Console must be enabled, configured and open as seen before.

  1.  Open this tree demo (Ajax switch type)
  2.  Expand "Baccara" node
  3.  Expand "Grand Collection"
  4.  Collapse "Grand Collection"

 As you can see the child nodes below "Grand Collection" has been removed or hidden (FireBug's DOM inspector says they were removed).

<html xmlns="http://www.w3.org/1999/xhtml" lang="en"><head></head><body><div xmlns:rich="http://richfaces.ajax4jsf.org/rich"><table border="0" cellpadding="0" cellspacing="0" class="rich-tree-node" id="j_id354:j_id355:0:1::j_id358"><tbody><tr id="j_id354:j_id355:0:1::j_id358:mainRow" onclick=" "><td class="rich-tree-node-handleicon rich-tree-h-ic-line-node" id="j_id354:j_id355:0:1::j_id358:handles" style="background-image:expression(this.parentNode.parentNode.parentNode.nextSibling.nextSibling ? 'url(/richfaces-demo/a4j/g/3_3_3.Finalorg.richfaces.renderkit.html.images.TreeLineNodeImage/DATB/eAH7!!!!72fXGBgYACWpBbU_.jsf)' : 'url(/richfaces-demo/a4j/g/3_3_3.Finalorg.richfaces.renderkit.html.images.TreeLineLastImage/DATB/eAH7!!!!72fXGBgYACWpBbU_.jsf)')"><div><a class="rich-tree-node-handle" href="#" id="j_id354:j_id355:0:1::j_id358:handle" onclick="var c = Tree.Item.findComponent(this); if (!c) return; c.fireExpansionEvent();;A4J.AJAX.Submit('j_id354',event,{'similarityGroupingId':'j_id354:j_id355:0:1::j_id358','parameters':{'j_id354:j_id355:0:1::j_id358AjaxExpanded':true,'j_id354:j_id355:0:1::j_id358NodeExpanded':'true'} } ); return false;"><img alt="" class="rich-tree-node-handleicon-collapsed" id="j_id354:j_id355:0:1::j_id358:handle:img:collapsed" src="/richfaces-demo/a4j/g/3_3_3.Finalorg.richfaces.renderkit.html.images.TreePlusImage/DATB/eAH7!!!!72fXGBgYACWpBbU_.jsf" style=";border:0" /><img alt="" class="rich-tree-node-handleicon-expanded" id="j_id354:j_id355:0:1::j_id358:handle:img:expanded" src="/richfaces-demo/a4j/g/3_3_3.Finalorg.richfaces.renderkit.html.images.TreeMinusImage/DATB/eAH7!!!!72fXGBgYACWpBbU_.jsf" style="display: none;;border:0" /></a></div></td><td class="rich-tree-node-icon rich-tree-h-ic-line-clp" id="j_id354:j_id355:0:1::j_id358:icon" rich:draggableoptions="{'parameters':{'dragSourceId':'j_id354:j_id355:0:1::j_id358','j_id354:j_id355:0:1::j_id358':'j_id354:j_id355:0:1::j_id358'} } " rich:dropzoneoptions="{} "><img alt="" class="rich-tree-h-ic-img" src="/richfaces-demo/images/tree/disc.gif" /></td><td class="rich-tree-node-text " id="j_id354:j_id355:0:1::j_id358:text" rich:highlightedclass="rich-tree-node-highlighted" rich:selectedclass="rich-tree-node-selected">Grand Collection</td></tr></tbody></table><div id="j_id354:j_id355:0:1::j_id358:childs" style="display: none;" class="rich-tree-node-children rich-tree-h-ic-line"></div><div id="j_id354:j_id355:script" class="rich-tree-h"><script type="text/javascript">$('j_id354:j_id355').component.refreshAfterAjax(['j_id354:j_id355:0:1::j_id358'] ,'')</script></div></div><div xmlns:rich="http://richfaces.ajax4jsf.org/rich"></div><div xmlns:rich="http://richfaces.ajax4jsf.org/rich"></div><div xmlns:rich="http://richfaces.ajax4jsf.org/rich"></div><div xmlns:rich="http://richfaces.ajax4jsf.org/rich"></div><meta name="Ajax-Update-Ids" content="j_id354:j_id355:0:1::j_id358,j_id354:j_id355:0:1::j_id358:childs,j_id354:j_id355:script" /><span id="ajax-view-state"><input type="hidden" name="javax.faces.ViewState" id="javax.faces.ViewState" value="j_id3" /></span><meta id="Ajax-Response" name="Ajax-Response" content="true" /><meta name="Ajax-Update-Ids" content="j_id354:j_id355:0:1::j_id358,j_id354:j_id355:0:1::j_id358:childs,j_id354:j_id355:script" /><span id="ajax-view-state"><input type="hidden" name="javax.faces.ViewState" id="javax.faces.ViewState" value="j_id3" /></span><meta id="Ajax-Response" name="Ajax-Response" content="true" /></body></html>

 As you can see too much HTML code has been sent for not much of a visual change.

 A more severe performance penalty:

  1.  Open the Extended Data Table Demo
  2.  On "State Name" paste "Alaska" (paste the name from clipboard), one row is shown
  3.  Paste "Alabama" replacing "Alaska" (again paste from clipboard selecting Alaska first), again one different row is shown.

The answer (HTML code) is too big to put here, 3.474 bytes, if you inspect the result you will see a complete rewrite of the table including header.

IceFaces

  1. Open the Calendar demo
  2. Click on any different day

 Something like this is the last AJAX response:

The answer (XML with metadata) is really big, 6.452 bytes, for a simple day change according to visual changes.

MyFaces/Trinidad

  1. Open this Tree Table Demo
  2. Expand node_0_0
  3. Expand node_0_0_0 (node node_0_0_0_ is shown)
  4. Collapse node_0_0_0 (hides/removes node_0_0_0_0) 

The last AJAX response is too big to put here, 18.765 bytes, because is a complete rewrite of the tree component.

Update: a live demo of ADF Faces components is here and they seem to work fine as expected, that is, the ratio between code sent to the client and visual change is "correct" (in spite of HTML layout is very verbose  the code sent to the client is almost the same to be displayed).

OpenFaces

  1.  Open the Tree Table demo
  2.  Expand "Re: Scalling an image"
  3.  Expand the new child  "Re: Scalling an image"

 The last AJAX response is

<?xml version="1.0" encoding="UTF-8"?><ajaxResponse><head> </head><updatable id="subRows:2" type="portion" value="<tr><td><table cellspacing="0" cellpadding="0" class="o_cellWrapper"><tr><td class="o_treetable_indent"><div class="o_treetable_indent"></div></td><td class="o_treetable_indent"><div class="o_treetable_indent"></div></td><td class="o_treetable_indent"><div class="o_treetable_indent"></div></td><td class="o_treetable_indent"><div class="o_treetable_indent"></div></td><td><span class="treeTableText">Re: Scaling an image</span></td></tr></table></td><td><span class="treeTableText">Christian Smile</span></td><td><span class="treeTableText">Aug 3, 2007</span></td></tr>" data="{"structureMap":{"0":"1"}}" scripts="<script>O$.updateViewId('j_id3:j_id6');</script>" /></ajaxResponse>

 This code is very reasonable according to the change (a new child node/table row).

 Nevertheless some component miserably fails:

  1.  Open the Data Table demo
  2.  Select "AK" as "State", resulting one row.
  3.  Replace with "AR", resulting again a new row

  The last AJAX result is too big, 38.209 bytes,  because is a complete rewrite of the table including headers.

PrimeFaces

The AJAX answers of all tested examples were very reasonable. Said this, PrimeFaces lacks of a "filtered table component" or similar, the Achilles's heel of other JSF implementations.

Update: As Cagatay Civici (one of the fathers of PrimeFaces) points out, PrimeFaces has a filltered table, this component works fine regarding to the ratio of visual change/code sent to client (try to do the same tests as prvious frameworks).

Vaadin

This is the first non-JSF framework.

Open the Tree single selection demo

Select "Dell OptiPlex GX240"

Click  "Apply" button (no change is needed)

This is the last AJAX answer:

for(;;);[{"changes":[["change",{"format": "uidl","pid": "PID190"},["12",{"id": "PID190","immediate":true,"caption": "Hardware Inventory","selectmode": "single","nullselect":true,"v":{"action":"","selected":["2"],"expand":[],"collapse":[],"newitem":[]}},["node",{"caption": "Desktops","key": "1","expanded":true,"al":["1","2"]},["leaf",{"caption": "Dell OptiPlex GX240","key": "2","selected":true,"al":["1","2"]}],["leaf",{"caption": "Dell OptiPlex GX260","key": "3","al":["1","2"]}],["leaf",{"caption": "Dell OptiPlex GX280","key": "4","al":["1","2"]}]],["node",{"caption": "Monitors","key": "5","expanded":true,"al":["1","2"]},["leaf",{"caption": "Benq T190HD","key": "6","al":["1","2"]}],["leaf",{"caption": "Benq T220HD","key": "7","al":["1","2"]}],["leaf",{"caption": "Benq T240HD","key": "8","al":["1","2"]}]],["node",{"caption": "Laptops","key": "9","expanded":true,"al":["1","2"]},["leaf",{"caption": "IBM ThinkPad T40","key": "10","al":["1","2"]}],["leaf",{"caption": "IBM ThinkPad T43","key": "11","al":["1","2"]}],["leaf",{"caption": "IBM ThinkPad T60","key": "12","al":["1","2"]}]],["actions",{},["action",{"caption": "Add child item","key": "1"}],["action",{"caption": "Delete","key": "2"}]]]]], "meta" : {}, "resources" : {}, "locales":[]}]

It seems not very much, but if you review the code the entire tree is being rebuilt again. 

ZK

Another non-JSF framework. In the last versions ZK embrace an hybrid approach, most of the visual logic is in client as JavaScript components, the server sends to the client high level commands to the high level client library (Vaadin is not different). I have not found a component sending too much code from client (according to the visual change) in ZK's demo.

ItsNat

The last framework studied, again a non-JSF framework. 

In ItsNat the server keeps the same DOM state as in client and through DOM mutation events any change to the DOM in server automatically generates the JavaScript necessary to update the client accordingly.  

  1. Open the demo
  2. Click on the handler of "Core" folder, the child nodes (11) are hidden.

Result code of the AJAX event:

itsNatDoc.addNodeCache(["cn_10","cn_14","0,1,1,0,0",["cn_15","cn_16"]]);
itsNatDoc.setAttribute2("cn_14","src","img/tree/tree_node_collapse.gif");
itsNatDoc.setAttribute2(["cn_15","cn_17","1"],"src","img/tree/tree_folder_close.gif");
itsNatDoc.setAttribute2(["cn_16","cn_18","1,0",["cn_19"]],"style","display:none");
itsNatDoc.setAttribute2(["cn_19","cn_20","1"],"style","display:none");
itsNatDoc.setAttribute2(["cn_19","cn_21","2"],"style","display:none");
itsNatDoc.setAttribute2(["cn_19","cn_22","3"],"style","display:none");
itsNatDoc.setAttribute2(["cn_19","cn_23","4"],"style","display:none");
itsNatDoc.setAttribute2(["cn_19","cn_24","5"],"style","display:none");
itsNatDoc.setAttribute2(["cn_19","cn_25","6"],"style","display:none");
itsNatDoc.setAttribute2(["cn_19","cn_26","7"],"style","display:none");
itsNatDoc.setAttribute2(["cn_19","cn_27","8"],"style","display:none");
itsNatDoc.setAttribute2(["cn_19","cn_28","9"],"style","display:none");
itsNatDoc.setAttribute2(["cn_19","cn_29","10"],"style","display:none");

No surprises.

Another test

Open this Tree demo

Click on "Insert Child". A new child node ("Actors") is inserted and a new log message is added.

AJAX result code:

itsNatDoc.removeAttribute2(["cn_15","cn_39","13"],"style");
itsNatDoc.setInnerHTML2("cn_39","<div><input> click</div><div>javax.swing.event.TreeModelEvent 13802934 path [Grey's Anatomy, Actors] indices [ 4 ] children [ Actors ]</div>");
var child = itsNatDoc.doc.createElement("li");
itsNatDoc.setAttribute(child,"style","padding:1px;");
itsNatDoc.appendChild2(["cn_17","cn_40","0,1,1,1",["cn_41","cn_42"]],child);
itsNatDoc.setInnerHTML(child,"<span><img src=\"img/tree/tree_node_expanded.gif\"><img src=\"img/tree/tree_folder_open.gif\"><span><b>Label</b></span></span>\n <ul style=\"list-style-type: none;\"></ul>\n ");
itsNatDoc.setTextData2(["cn_40","cn_43","4,0,2,0",["cn_44","cn_45"]],null,"Actors");
itsNatDoc.setAttribute2(["cn_45","cn_46","0"],"style","display:none");
itsNatDoc.setAttribute2(["cn_45","cn_47","1"],"src","img/tree/gear.gif");

Again no surprises.


And the Winner is...

There is no winner because only some components have been tested.

Having said this, apparently the only JSF implementation free of serious performance penalties is PrimeFaces.

In non-JSF frameworks using a very high level JS library like in Vaadin or ZK (PrimeFaces?) helps very much to reduce the network bandwidth (in spite of the fact that some components in Vaadin have serious performance problems), this cannot be said for client performance because in ItsNat the exact JS DOM code is sent to the client.

On the other side a high level JS library complicates custom component development (beyond composition) because the server does not help very much but this is another story, and another article.

 

Framework Java (programming language) Database AJAX Comparison (grammar)

Opinions expressed by DZone contributors are their own.

Related

  • Java 2021: What Frameworks and Trends for This New Year?
  • Code Generation in CUBA: What makes the magic
  • Modern Cloud-Native Jakarta EE Frameworks: Tips, Challenges, and Trends.
  • What Java DAO Layer Is Best for Your Project

Comments

Partner Resources

X

ABOUT US

  • About DZone
  • Send feedback
  • Careers
  • Sitemap

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 3343 Perimeter Hill Drive
  • Suite 100
  • Nashville, TN 37211
  • support@dzone.com

Let's be friends: