Sunday, November 25, 2012

Design Patterns For Object-Oriented JavaScript

I completed a refactoring for our ERP’s JavaScript codes which was developed previously in functional way. Our target was to convert functional code mess to object-oriented one similar to our server-side Java codes. Years ago I had inspected some object-oriented JavaScript codes but I’d found it very complex to implement them in our library. However, today JavaScript is living its golden age and that couraged me to reconsider object-oriented techniques.

I read some books about writing object-oriented codes and collected some useful patterns to use in my refactoring. I witnessed that some suggested patterns on those books are very complex and cumbersome to use. Here I’ll share some simple patterns I used during my conversion. It was very challenging that I had to keep existing functionaly but there were many script files and functionality. In existing functional code base, everthing was global and everthing was function. One reason that leads us to make such a refactoring was the necessity to use multiple instances of user interface components. Component states and behaviours were organized as file but that was not enough to keep states of multiple instances. Lastly, we were using Internet Explorer’s old HTC files for components and it is not supported anymore.

After making refactoring the result was amazing that I didn’t even expect so. Before that work, I was assuming that I know JavaScript good enough to write solid code but I concluded that I was wrong. Although object-orientation in JavaScript is not as good as Java and many of them are work-arounds, it is still advantagous compared with functional JavaScript codes.

Here are the patterns I used in the refactoring (I tested them with latest versions of IE, Firefox and Chrome):

1. Web Coding Principles


Principles I used during my refactoring are following:
  • Feature-Detect Rather Than Browser-Detect
  • Separation of concerns (Structure + Style + Behavior -> HTML + CSS + JavaScript)
  • Avoid Cluttering The Global Namespace
  • Modularization: Lazy Loading.

2. Three Ways of Function Creation


Let’s start with basics. There are 3 ways to create a function, one can use where it is appropriate (Note that a function is also an object):

With Function Declaration:

It is evaluated at parse-time, and can be used anywhere in the current scope.
 function myFunction(){
  console.log('hello');
 }
 myFunction(); //hello
 

With Function Constructor:

It is evaluated at run-time and can be used after it is created.
 var variablename = new Function(Arg1, Arg2..., "Function Body");

 var myFunction = new Function("console.log('hello')");
 myFunction(); // hello

 var myFunction = new Function("x", "y", "return x*y;");
 console.log(myFunction(4,3)); // 12
 

With Function Expression:

It is evaluated at run-time and can be used after it is created. It is also named as “Anonymous Function”.
 var myFunction = function(){
  console.log('hello');
 };
 myFunction(); // hello
 
or
 (function(){
  console.log('hello');
 })(); // hello
 

3. Block Scope Pattern


Block scope means that variables defined within a curly bracket can not be accessed outside the bracket. JavaScript doesn’t support block scope. The only way to achieve block scope in JavaScript is to use anonymous function in such a way that once we create it we call it. In this way global namespace cluttering is also prevented. Block Scope in JavaScript:
(function(){
 ...
})();

if(true){
 var q = 10;
}

{
 var x = 10;
}

for(var i= 0; i < 5; i++){
 var y = i;
}

(function(){
 var z = 20;
})();

console.log(q); // 10
console.log(x); // 10
console.log(window.x); // 10
console.log(y); // 4
console.log(i); //5
console.log(z); // “z is undefined” error

4. Type Constructor Function Pattern


Every function is also a type and new instances from these functions can be created with “new” keyword. Function declaration behaves as constructor and also called “Constructor Function”. In constructor functions, prototype methods and fields can be accessed.
function MyType(data){
 this.data = data;
}

var myInstance = new MyType("test");
console.log(myInstance.data); // test

5. Object Literal Pattern


It is very easy to create objects with object literals. It is also possible to create nested objects with it. To create object in standard way:
var myObject = {}; // or var emptyObject = new Object(); 
myObject.field1 = "value1";
myObject.childObject = {};
myObject.childObject.field2 = "value2";
myObject.method1 = function(){
 return "method1 called";
};

console.log(myObject.field1); // value1
console.log(myObject.childObject.field2); // value2 
console.log(myObject.method1()); //method1 called
To create object with object literal:
var myObject = {
 field1:"value1",
 childObject:{
  field2:"value2"
 },
 method1:function(){
  return "method1 called";
 }
};

console.log(myObject.field1); // value1
console.log(myObject.childObject.field2); // value2 
console.log(myObject.method1()); //method1 called

6. "that" Pattern


In inner functions of objects created from function constructors with “new” operator we may need to access to the uppermost function object. To achieve that, in uppermost function constructor, “this” is assigned to a variable which is named as “that”(some uses “self” as name). In this way, we can refer to the uppermost object with “that” variable in inner scopes.
function Test(){
 var that = this;
 this.testField = "parent";

 innerMethod();

 function innerMethod(){
  this.testField = "child";
  console.log(this.testField); // child
  console.log(that.testField); // parent
 }
}

var x = new Test();
Beware that if function is directly called, this refers to current “window” object not the function object:
function Test(){
 console.log(this.name); // I'm a window
 innerMethod();

 function innerMethod(){
  console.log(this.name); // I'm a window
 }
}

window.name = "I'm a window";
Test();

7. Public Function Pattern


Prototype methods “public” and can’t be restricted. Prototype methods are shared among instances and if it is possible, prototype methods and fields should be used for “public” access.
function PublicTest(){
 this.publicFunction1 = function(){
  return "test1";
 };
}

PublicTest.prototype.publicFunction2 = function (parameter) {
 return parameter;
};

var x = new PublicTest();
console.log(x.publicFunction1()); // test1
console.log(x.publicFunction2("test2")); //test2

8. Public Field Pattern


For public field need, prototype or instance can be used. Prototype fields and methods are shared by new instances (Prototype object is also shared). If a new instance changes it, it is not reflected to the other instances.
function PublicTest(){
 this.publicField1 = "test1";
 this["publicField2"] = "test2";
}
PublicTest.prototype.publicField3 = "test3";

PublicTest.prototype.testRead = function(){
 console.log(this.publicField1); // test1
 console.log(this.publicField2); // test2
 console.log(this.publicField3); // test3
 console.log(this.publicField4); // test4
};

PublicTest.prototype.testWrite = function(){
 this.publicField3 = "test3 written";
};

var x = new PublicTest();
x.publicField4 = "test4 ";

x.testRead(); // test1 test2 test3 test4

var y = new PublicTest();
y.testWrite();
var z = new PublicTest();

console.log(y.publicField3); // test3 written
console.log(z.publicField3); // test3

9. Private Field Pattern


In JavaScript, there is no private field support by language. It can be achieved with “Closures”. Variables defined within constructor function can be used as private fields. Any methods using private fields should be declared in constructor function (Prototype methods can’t be declared in constructor function and used with private fields). Private methods setter and getter functions should be declared in constructor function.
function PrivateTest(){
 var _privateField = "FieldDefaultVal";
 
 this.getPrivateField = function(){
  return _privateField;
 };
 this.setPrivateField = function(newValue){
  _privateField = newValue;
 };
 this.otherPublicMethod = function(){
  _privateField = _privateField + " changed";
  return this.getPrivateField();
 };
}

PrivateTest.prototype.publicPrototypeMethod = function(){
 this.setPrivateField("Changed  from prototype method");
 return this.getPrivateField();
};

var x = new PrivateTest();

console.log(x.getPrivateField()); // FieldDefaultVal
console.log(x.otherPublicMethod()); // FieldDefaultVal changed
console.log(x.publicPrototypeMethod()); // Changed from prototype method

10. Private Function Pattern


They are also named as “Nested or Inner Functions”. Private functions are defined within another function and can’t be accessed from outside. Private functions can be declared in any part of function.
function Parent (parameter){
 var that = this;
 this.publicVariable = "bar"; 
 var privateVariable = "foo"; 
 this.publicVariable = privateMethod();

 function privateMethod() {
  console.log(parameter);
  console.log(privateVariable);
  console.log(that.publicVariable); // this refers to inner function, so that we reached the parent function object with "that"
  return "test";
 }
}
Or
function Parent (parameter){
 var that = this;
 this.publicVariable = "bar"; 
 var privateVariable = "foo"; 
 var privateMethod = function() {
  console.log(parameter);
  console.log(privateVariable);
  console.log(that.publicVariable);
  return "test";
 };

 this.publicVariable = privateMethod();

}

var x = new Parent("parent"); // parent foo bar
console.log(x.publicVariable); // test
console.log(x.privateVariable); // undefined
If private inner function is returned outside, its methods can be called from outside:
function Outer(){
 return new Inner();

 //private inner
 function Inner(){
  this.sayHello = function(){
   console.log("Hello World");
  }
 }
}

(new Outer()).sayHello(); // Hello World

11. Privileged Function&Field Pattern


Prototype methods can’t access private fields and everything attached to this is also “public”. We need a way to declare methods and fields so that they are accessed by any methods of object but not outside, which means privileged access. For this purpose, following can be used:
var Car = (function(){
 var protectedStaticField = "foo";

 function Car(){
  this.publicField = "car";
 }

 Car.prototype.publicField2 = "bar";

 Car.prototype.testAccess = function(){
  console.log(protectedFunction());
  console.log(protectedStaticField);
 };

 return Car;
 
 function protectedFunction(){
  return "test"; 
 }

})();

var x = new Car();
x.testAccess(); // test foo
console.log(x.publicField); // car
console.log(x.publicField2); // bar
console.log(x.protectedStaticField); // undefined
console.log(x.protectedFunction()); // Error

12. Static Function&Field Pattern


Again, there is no a direct support for static members. Constructor functions are used for this purpose. Static members can’t be accessed with “this” keyword in its functions.
function Factory(){
}

Factory.staticFunction = function (){
return "static test";
};

Factory.staticField = "test";

Factory.prototype.test = function(){
console.log(this.staticField); // undefined
console.log(Factory.staticField); // test
console.log(Factory.staticFunction()); //static test
}

var x = new Factory();
x.test();

13. Singleton Pattern


If we need to use one instance of an object, this pattern can be used.
var Logger = {
 enabled:true,
 log: function(logText){
  if(!this.enabled)
   return;
  if(console && console.log)
   console.log(logText);
  else
   alert(logText);
 }
}
Or
function Logger(){
}
Logger.enabled = true;
Logger.log = function(logText){
 if(!Logger.enabled)
  return;
 if(console && console.log)
  console.log(logText);
 else
  alert(logText);
};

Logger.log("test"); // test
Logger.enabled = false; 
Logger.log("test"); // 

14. Prototypal Inheritance Pattern


Here is the inheritance implementation I used:
//base function
function Parent(){
 console.log("parent");
}
Parent.prototype = {
 parentData: "parent data",
 parentMethod: function(parameter){
  return "parent method"; 
 },
 overrideMethod: function(parameter){
  return parameter + " overrided parent method"; 
 }
}

function Child(){
//Its super constructor is not called by JS Engine we have to invoke it
 Parent.call(this);
 console.log("child");
}

//inheritance
Child.prototype = new Parent();
//nesne tipine bakınca doğru değeri bulabilmek için
Child.prototype.constructor = Child;

//lets add extented functions
Child.prototype.extensionMethod = function(){
 return "child's " + this.parentData;
};
One important limitation about “override inherited functions”; when calling parent’s method from child, you can’t access parent’s private instance fields. It behaves like a static method (Except “this” variable). To bypass that problem, you can pass instance fields as parameter when calling parent’s method. We can only access parent’s private fields in constructor method.
//override inherited functions
Child.prototype.overrideMethod = function(){
 //parent's method is called
 return "Invoking from child" + Parent.prototype.overrideMethod.call(this, " test");
}

var x = new Child();
console.log(x.extensionMethod()); //child's parent data
console.log(x.parentData); //parent data
console.log(x.parentMethod()); //parent method
console.log(x.overrideMethod()); //Invoking from child test overrided parent method


var x = new Child(); // parent child
console.log(x instanceof Parent); //true
console.log(x instanceof Child); //true
In child object’s constructor, we can access parent’s members:
function Parent(){
}
Parent.prototype.parentData = "test";

//inheritance
Child.prototype = new Parent ();

function Child(){
console.log(this.parentData); // test
}

var x = new Child();
console.log(x.parentData); // test

console.log(x instanceof Parent); // true
console.log(x instanceof Child); //true

15. Behavior (Decarator) Pattern


One object’s behavior is defined separately and it is activated in certain cases. In this way, we avoid to define new object types and its inheritance while increasing hierarchy level.
function InputTextComponent(){
}

InputTextComponent.prototype.addAutoSuggestBehaviour = function(){
 this.autoSuggestBehaviour = new AutoSuggest(this);
 console.log("AutoSuggest enabled");
};

InputTextComponent.prototype.removeAutoSuggestBehaviour = function(){
 this.autoSuggestBehaviour.unbind();
 delete this.autoSuggestBehaviour;
 console.log("AutoSuggest disabled");
};

function AutoSuggest(inputTextComp){
 this.bind(inputTextComp);
}

AutoSuggest.prototype.bind = function(inputTextComp){
 // attach keydown event etc.
};

AutoSuggest.prototype.unbind = function(){
 // detach keydown event etc.
};


var x = new InputTextComponent();
x.addAutoSuggestBehaviour(); // AutoSuggest enabled
x.removeAutoSuggestBehaviour(); // AutoSuggest disabled

16. Event (Observer or Publish-Subscribe) Pattern


We need custom events in JavaScript codes as well. Event programming has many advantages. Here is a typical event pattern:
function EventManager(){
}
var listeners = {};

EventManager.fireEvent = function(eventName, eventProperties) {
 if (!listeners[eventName]) 
  return;

 for (var i = 0; i < listeners[eventName].length; i++) {
  listeners[eventName][i](eventProperties);
 }
};

EventManager.addListener = function(eventName, callback) {
 if (!listeners[eventName]) 
  listeners[eventName] = [];
 listeners[eventName].push(callback);
};

EventManager.removeListener = function(eventName, callback) {
 if (!listeners[eventName]) 
  return;
 for (var i = 0; i < listeners[eventName].length; i++) {
  if (listeners[eventName][i] == callback) {
   delete listeners[eventName][i];
   return;
  }
 }
};

EventManager.addListener("myCustomEvent", function(props){
 console.log("Invoked event: " + props.test);
});

EventManager.fireEvent("myCustomEvent", {test:"testValue"}); // Invoked event: testValue

17. Logger Pattern


Logging is important in JavaScript codes especially for debugging. We can define a singleton logger and it can be switched on or off from one place:
var logger = new MyLogger(false);//false means not enabled

logger.log("debugging value x : " + x);

18. Method Chaining Pattern


Method chaining is one of the most used patterns JavaScript libraries. The key point for chaining that you return object reference every time you call a function.
function Car(owner){
 this.owner = owner;
}

Car.prototype.run = function(){
 console.log("Car is driven by Mr. " + this.owner);
 return this;
}

Car.prototype.stop = function(cause){
 console.log("Since "+ cause + ", car is stopped by Mr. " + this.owner);
 return this;
}

var x = new Car("Foo Lee");
x.run().stop("traffic jam").run(); // Car is driven by Mr. Foo Lee
        // Since traffic jam, car is stopped by Mr. Foo Lee
       // Car is driven by Mr. Foo Lee


19. Simple JavaScript Component Model (JSCOM) Pattern


We add new behaviors to the HTML elements and DOM objects with JavaScript. These enrichments can be combined in a component structure. Here is a commonly used pattern to bind JavaScript objects to DOM objects. In this way, we can collect behaviors and manage their lifecycles.

1- Define JavaScript Component:

function InputTextNumberComponent(){
}

InputTextNumberComponent.prototype.bindDOMElement = function(domElement){
 domElement.onchange = function(){
  //just a format
  domElement.value = "-" + domElement.value + "-";
 };
domElement.jsComponent = this; //Expando property
 this.domElement = domElement;
};

InputTextNumberComponent.prototype.resetValue = function(){
 this.domElement.value = "";
};

2- Define CSS Entries to Correlate HTML Elements with JavaScript Components:

<style type="text/css">
.inputTextNumber { text-align:right; }
</style>

3- When page loaded (or DOM ready), detect the component and create-initialize it and bind to the DOM object (Note that for large web pages, this detection is expensive if many components are searched. For that reason some libraries requires to create components manually instead of auto-detection, by finding them with “id” attribute):

window.onload = function(){
 var inputTextNumbers = document.getElementsByClassName("inputTextNumber");
 for(var i = 0; i < inputTextNumbers.length; i++){
  var myComp = new InputTextNumberComponent();
  myComp.bindDOMElement(inputTextNumbers.item(i));
 }
};
HTML element should be as following:
<input type="text" class="inputTxtNumber" name="NumberField" size="10" value="Click me!" onClick="this.jsComponent.resetValue()">

20. Module (AMD-Asynchronous Module Definition) Pattern


Module pattern provides “lazy loading”, “scoping” and “dependency management”. There are many approaches but I recommend “Every JavaScript file is a module” one. In module files, we define new types, import some types from other modules and export our public types.
Module.define('module1.js',['dependent_module1.js','dependent_module2.js',...],function(dependentMod1, dependentMod2) {

//TYPE DEFINITIONS

function ExportedType1(){
 // use of dependent module’s types
 var dependentType = new dependentMod1.DependentType1();
 ...
}

function ExportedType2(){
}
...

// EXPORTS
return { ExportedType1: ExportedType1, ExportedType2: ExportedType2,...};

});
To use a module (A parameter can be specified to invoke given function asynchronously or synchronously):
Module.use(["module1.js"], function(module1){
 console.log("Loaded file module1.js!");
var type1 = new module1.ExportedType1();
});

Resources:

http://www.amazon.com/JavaScript-Design-Patterns-Recipes-Problem-Solution/dp/159059908X
http://eloquentjavascript.net/
http://www.amazon.com/JavaScript-Good-Parts-Douglas-Crockford/dp/0596517742
http://libraryinstitute.wordpress.com/2010/12/01/loading-javascript-modules/
http://addyosmani.com/resources/essentialjsdesignpatterns/book/
http://www.ibm.com/developerworks/web/library/wa-jsframeworks/

Saturday, July 16, 2011

Java Web Application Upgrade Story From 1.2 to 1.5: Lessons Learned

We were busy during past months while upgrading our ERP application. The upgrade wasn’t a piece of cake for us. There are always 2 rules about upgrade; it has a cost and it is painful. If it contains many elements, then your compatibility combat begins. I want to share our journey and some lessons learned. We transformed 70 web applications and about 1000 db tables to new version. We couldn’t upgrade to the latest versions because of license and fear of probable bugs on latest versions.

Let’s look at the versions and elements of upgrade:

Before:
Java 1.2, WebSphere 3.5, DB2 7.1, VisualAge For Java 3.5, Team Repository

After:
Java 1.5 (5), WebSphere 6.1, DB2 9.1, Rational Application Developer For WebSphere 7.5, ClearCase 7.1


1. The most changing part was application configuration: In previous WebSphere version, we were using the file system for application elements and that path was defined as classpath in application server, that was ver easy with some disadvantages. In Java EE 5, EAR and WAR package structure are used. We had to map our applications to this new package system. Session, classpath and classloader behaviours are very closely related with this mapping.

There were 2 options for application packaging:
a-Packaging each web application as WAR within one EAR(One EAR): In WebSphere, we can’t restart WARs individually and install options are generally bound to EAR structure. Because of that, we didn’t select this option.

b-Packaging each web application as one WAR and one EAR(Many EARs): We used this option. In this option, every application can be started, stopped, upgraded without stopping application server. However, there is a shared session problem. In Java EE 5 specs, every WAR has its own independent session. WebSphere supports shared session among WARs within only one EAR.

Shared Session Problem Solution
We needed shared session through all web applications and EARs. What we did was, to develop “Shared Session Support Among EARs” ourselves. It wasn’t easy to achieve this, we had to use session invalidation events and then temporarily store the objects of invalidating session. When user enters that application, we filled the new session with the previuosly created session objects. Another interesting point is that WebSphere uses same Session ID for new web applicaions. For a certion user, session objects are differenet but session ID is same.

Shared Library Problem Solution
Another problem was configuring application classpaths. We needed 2 basic classpath (now called as “shared lib” in WebSphere) requirements for library visibility:

a- Inter-Application-Level Classpath: For instance, one application needs to see a certaion application classes. We should provide that visibility without adding to global container-level classpath. Fortunately, a WebSphere extension eanbled us to make such a configuration. What we did was to add WEB-INF/classes path to the shared lib section of other application. One note about that is you should choose “ClassLoader Multiple Policy”, otherwise your application restart doesn’t take effect since classloaders are not renewed.

b-Container-Level Classpath: This is required if you need global visibility of some libraries. This is achieved in WebSphere with ClassLoader creation in Admin Console. You firstly define your library as a shared lib. Then you create a new classloader containing that shared lib entries.


2. DB2 is perfectly stable: "DB2 is DB2 is DB2." This mantra holds true. The easiest element of upgrade was DB2. What we need is to restore a 7.1 backup image to 8.1 then again to restore its backup to 9.1 version. You can’t restore a backup of 7.1 version to directly to 9.1 version. One extra work was to migrating an AIX database to the Windows system. In DB2, you can’t restore a backup image from other OSs. There is a utility to export and import form one system to another: db2move

3. The hardest part was to configure ClearCase environment: From VisualAge, we exported source codes, then imported to the RAD, that was a straightforward task. The problematic part is to build a Team environment for source code. In VAJ, there were a basic and simple Team system. We had to become familiar with versioning concepts like “Check-in”, “Check-out”, “Hijack”, “Baseline”, “Branch”, “Activity” etc. Initial setup and configuration of ClearCase server was another rough job. We had to outsource that job to an external consultant. I strongly recommend that you should consult to someone else if you are not familiar with ClearCase and Eclipse connection. There are many confusing configuration options for ClearCase. We used web-client type with snapshot views. Its performance is not good but enough for now.

4. Upgrade periodically for performance: Yes, to update frequently is a cumbersome for agile teams but becoming too late may increase upgrade cost. New versions may bring not only new features but new performance improvements. In Java 1.2, the most bothering part was GC; it was stopping all applications. With Java 1.5, “Incremantal GC” performance is excellent. After the upgrade, users were very satisfied with performance. Report execution times decreased from 10 minutes to 10 seconds. Every team should plan and reserve a time for upgrade in their agenda.

5. SSD disks versus HDD disks: We bought some new servers during upgrade. In one server configuration, we used SSD disk for its famous performance advantages for db-driven applications. One mistake of us was to buy only 2 SSD disks, and using it with RAID1(mirroring) configuration. Its performance was equivalent with 4 SAS disks with RAID5 configuration. We needed to buy 2 new SSD disk(Using RAID5) for better performance. I found a benchmark which depict the case.

As I understand, even we use 4 SSD disks, its speed won’t be superior as we expected. I read many articles mentioning 4 or 10 times performance but we didn’t get it. (Our new servers were Dell PowerEdge.). Additionally, SSD disks are highly expensive compared with classical HDDs.

6. 32 bit versus 64 bit: We were unable to use 64 bit versions for some reasons. 64 bit version should be supported by OS, DB2 and WebSphere. For WebSphere, 64 bit means more heap space more than 1.5 GB. For DB2, 64 bit means larger memory for DB which is more than 3 GB. In 64 bit, DB2 buffer pools can leverage more memory and that may result good performance gain. WebSphere is also bundled as as 32-bit and 64-bit. WebSphere Express edition currently doesn't support 64-bit, expecting 64 support in coming releases.

Sunday, August 22, 2010

Java EE Web Development Without JSF

As a Java web development team, we’re frequently asked if we plan to use JSF in our web applications. After some hearings from my developer colleagues about their experiences using JSF, I decided to analyze if JSF is right technology for some problems of web development. After reading specifications, inspecting implementation libraries, I reached the conclusion of not using JSF. Even JSF 2.0 version is not enough to change this result. Here, I’ll try to give my reasons for this decision. Although Sun was pushing this technology by removing the mention of JSP form the Java EE 6 Tutorial, we are expecting JSP to live in the future. JSP technology is simple and direct solution of a certain problem. You can get same functions promised by JSF with JSP and JavaScript with less cost. JSF is a big engineering effort but the problem lies within the nature of web architecture.

I’m not alone for having this point of view. There are many voices having doubts about this technology:

http://ptrthomas.wordpress.com/2009/05/15/jsf-sucks/
http://weblogs.java.net/blog/edburns/archive/2010/01/22/analysis-peter-thomass-jsf-critical-rant
http://www.theserverside.com/news/1364127/Rethinking-JSF-The-Real-Problem
http://www.theserverside.com/news/thread.tss?thread_id=43899
http://www.chrislhardin.com/2009/08/java-server-faces-vs-ajax-frameworkswhy.html
http://weblogs.java.net/blog/2006/06/07/programmer-productivity-jsf-and-netbeans

Here are my opinions about the disadvantages of JSF:

1- JSF Introduces A Redundant UI Layer: As I mentioned in my previous posts, complete server-side UI componentization is problematic since in web applications we have 2 runtimes; server-side and client-side. If we use a heavy server-side solution, we won’t have enough energy to develop in client-side. However, same functionality can be achieved with simple JSP and JavaScript code. Some developers tried to ignore client-side and JavaScript but the client-side is a very important part of web applications and can’t be hidden. As the JavaScript engines gets better and HTML gets new exciting improvements (add AJAX move), client-side gets more importance. We need lightweight component libraries with client-side abilities. If we talk about components, we should consider client-side components. MS IE’s HTC and Firefox XBL are some efforts on this direction. In recent HTML specifications, I expect a standard for HTML components (XBL 2.0) but it seems difficult to see widespread browser implementations. We are currently using MS IE’s HTC components for some simple behaviors like number-date-time formatting, AJAX-enabled input fields etc. Some components may be client-only but some big components may also need server-side support (For instance our DataGrid row is posted to server to save its state).

2- Tag Soup: When I see some new tags invented by a web framework, I admit its failure is started. Web standards became successful since they were simple and standard. New element names, new attribute names, new behaviors and new event models terribly increases learning curve without any real benefits. What I say is don’t reinvent current HTML tags. I think current DOM, JavaScript and CSS namespaces are already too extensive that a programmer could learn.

<learnthis:thenlearnthat dontforgetme="doyourememberme()" iamundocumentedsuperfeature />

3- Losing Extensibility and Flexibility: Component encapsulation makes it hard to modify UI behaviors. Let’s say you want to insert some HTML code into 3rd row of a data grid. That may not be available in current API set. There may be many scenarios that were simple in HTML base declarative form. I inspected many JSF list components and they are nothing more than simple HTML tables. Why do we pay extra complexity cost for little earning of encapsulation of HTML? Even most of JSF components are just repetition of current HTML elements. You can find same function set of JSF implementations within JS libraries, nothing is new.

4- Complexity of Binding, Bean Lifecycle, Navigation, Scope and Event Model: To get basic grasp of JSF is much more difficult than request-based server models. MVC simplicity is also lost. You can observe that complexity in increasing development times or difficulties in debugging and fixing problems of applications. Designing UIs is just another story, common denominator between programmer and graphics designer is lost, every programmer should be also good designer. A very strong IDE support is required to hide some complexities like WebObjects did years ago.

5- Performance: I’ve heard some complaints about JSF performance, it may be eliminated but It is a fact that it would anyway consume valuable server resources. As we develop complex components with JSF, their performance degradation would be a new area of bottleneck analysis.


In Java EE stack, some standards never got enough adoption and that lead developers to find better, simpler solutions. I think JSF is moving on the same direction with EJB. Some developers may feel themselves comfortable by using JSF; good engineering, clean and structured code but I don't.

So, what is alternative? My suggestion is to use JSPs, servlets and JavaScript libraries. You may use some web frameworks or JS libraries to get ready-use functions. (Note that, some web frameworks have similar problems with JSF) If you still need HTML componentization, you can use XBL in Firefox or HTC in Internet Explorer (later waiting XBL 2.0 standard adoption). In web application architecture, unfortunately we’ve always ignored client computing resources. PCs are getting faster, browser engines are becoming faster. It is time to leverage client-side as much as possible.