AngularJSFsimpliying JSF

Why are Angular Components more Successful than JSF Components?

At first glance, there are many similarities between Angular and JSF. Both offer a decent abstraction layer from the DOM, both offer two-way binding (yes, I know it’s optional since Angular2), and both use components as building blocks of the application. Even better, both frameworks offer a way to create your own custom components. The difference is that hardly anybody creates custom components in JSF. Angular programmers do it all the time.

Things get even more mysterious when you learn that JSF has been designed with creating components in mind. It should be easy. But the vast majority of developers doesn’t think so.

Angular: Components first

Angular takes components to a whole new level. When AngularJS 1.0 was released seven years ago (on Oct 20, 2010), that was a revolution. Developers used components all the time, no matter which framework they used. Everybody knew it’s a good idea to download or buy a powerful third-party framework. The idea was that powerful components like datatables or charts should be developed by experts.

AngularJS and its predecessors changed all that. They made the process of creating components much more democratic. They enabled everybody to create their own component. React and Angular 2+ go one step further down that road. They force every developer to write their own components. The entire program is built on custom components. There’s no way to avoid custom components.

That fundamental design decision forced the Angular team to make creating components as simple as possible. They did a great job. Angular components are powerful enough to cover every conceivable use case. At the same time, it’s easy to write them. Actually, it took me a while to realize that this isn’t the programming style I used before.

JSF: components as expert tools

JSF comes from an older tradition, and it’s focused much more on the enterprise market. In a big company, there’s a framework team providing useful stuff like standard architectures and reusable components.

Actually, that sounds better than it is. More often than not, those central framework teams aren’t accepted by the developers doing “the real work”. The central team imposes restrictions the developers “at the front” would like to circumvent. I suppose that’s part of the problem: the developers working for the customer just want their problem solved. The central framework developers have a different perspective. They want to find solutions solving the problems of every other developer.

This state of mind leads to very generic solutions, usually involving a lot of boiler-plate code and often including concepts which are either difficult to grasp or weird. It’s like in real life: trying to make everybody happy is doomed to fail.

But JSF has been developed with components in mind, hasn’t it?

Like I’ve mentioned before, JSF has been designed specifically to make it simple to create a component. But it was designed at a time when XML was state of the art. So you have to create an XML file (called “taglib”) to register your JSF library, you have to register each component and each attribute of the components within the XML file and you have assign ids to link the implementation to the declaration in the XML file.

Truth to tell, that’s not difficult, but it’s tedious, and there are many pitfalls along the way. Popular errors are putting the taglib into the wrong folder or adding typos to the ids. The baroque API of JSF doesn’t help, either. Most developers consider it difficult to call the Java API to create simple HTML code.

There’s another effect, and it’s probably even more important. For some reason, developers assumed they shouldn’t create JSF components. After a while, everybody believed it’s very hard to write such a component. I guess that was just a prejudice because few people actually tried, but that’s how things go.

JSF composite components

With the advent of JSF 2.0, the problem was addressed with the composite components. In my eyes, that was a huge step in the wrong direction. Composite components are defined using XML files. The result is a clumsy, verbose syntax and not being able to use “if” conditions or loops. It’s a typical Java enterprise solution: very ceremonious and not very flexible.

Consider this example (taken from the blog of Yong Mook Kim, aka Mkyong):

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:h="http://java.sun.com/jsf/html"
      xmlns:f="http://java.sun.com/jsf/core"
      xmlns:composite="http://java.sun.com/jsf/composite">

<composite:interface>
  <composite:attribute name="namelabel" />
  <composite:attribute name="nameValue" />
  <composite:attribute name="emaillabel" />
  <composite:attribute name="emailValue" />
  <composite:attribute name="registerButtonText" />
  <composite:attribute name="registerButtonAction"
                       method-signature="java.lang.String action()" />
</composite:interface>

<composite:implementation>
  <h:form>
    <h:message for="textPanel" style="color:red;" />
    <h:panelGrid columns="2" id="textPanel">
      #{cc.attrs.namelabel} :
      <h:inputText id="name" value="#{cc.attrs.nameValue}" />
      #{cc.attrs.emaillabel} :
      <h:inputText id="email" value="#{cc.attrs.emailValue}" />
    </h:panelGrid>
    <h:commandButton action="#{cc.attrs.registerButtonAction}"
                     value="#{cc.attrs.registerButtonText}"/>
  </h:form>
</composite:implementation>
</html>

This component definition consists of 32 lines. The component itself is defined in 11 lines (lines 20 through 30). The other two-thirds of the file are overhead.

Angular’s approach to defining components

Truth to tell, I doubt an Angular component consists of fewer lines of code. It just feels a lot more natural. There’s an HTML template corresponding to lines 20 through 30. The interface section is replaced by a TypeScript class.

This has several advantages over defining the interfaces in XML. A class is real code. In other words: you can debug it. Plus, you’ve got the full power of a programming language. Implementing loops and conditional rendering is a walk in the park compared to what you have to do in JSF. In fact, I often see desperate JSF programmers using the “c:” namespace. Usually, that works, but it’s not part of JSF, but of the older JSP standard, which doesn’t play well with JSF.

Angular’s locality principle

Every Angular component consists of four parts:

  • the HTML snippet, using the values of a “code behind” class
  • a class playing roughly the role of a “code behind” class in the .NET lingo
  • a CSS file (or SASS, or LESS, depending on your preferences)
  • an (optional) test class.

By convention, these four classes are always put into a common folder. So the HTML class isn’t far away from the “code behind” class. You see at first glance that the files belong together.

That’s what I call the locality principle of Angular. IMHO, it’s also a key to the success of Angular. Angular programmers define many, usually hundreds of components per application. The locality principle makes it easy to find out which files belong together.

Compare this to the JSF approach: in general, the XHTML file is in a completely different folder than the corresponding JSF bean. Either you’re using a clever naming convention, or you’re looking for your files all the time. In JSF, it usually takes a while to figure this out.

Adding insult to injury, JSF allows you to put your XHTML files into different folders. In the case of composite folders, that’s even mandatory. So I often seen projects putting the publicly visible XHTML files in src/main/webapp, the include files in src/main/webapp/WEB-INF and the composite components in the folder src/main/resources. In a recent project, I had to use pen and paper to keep track of the files.

Cutting a long story short: organizing your directory layout along technical layers is often a bad idea. Angular drops this idea, encouraging you to organize your project structure along business domains.

Shadow DOM

Angular’s shadow DOM is another important key to the success of the components. It allows you to design a component without influencing the design of other components accidentally. JSF programmers (and web developers in general) are familiar with the problem: each CSS rule they add applies to the entire page. In the case of a single page application, that may even be an entire application consisting of hundreds of views. So adding a CSS rule improving the layout of a view often ruins the layout of another view of the application.

Of course, it’s possible to solve the problem with JSF. However, the nice thing about Angular is that it makes it a no-brainer. If you want to modify the look and feel of the entire application, you change the global CSS file. If you want to apply face-paint to an individual component, you change the CSS file in the package of the component.

Before you ask: the shadow DOM is not a unique property of Angular. It’s a web standard that’s soon going to lift off. Currently, Angular simulates the shadow DOM by default, making it available to old browsers, too. Other frameworks support the shadow DOM, too, but JSF definitely doesn’t.

What might a JSF port of the ideas of Angular look like?

I believe it needs three ingredients to make components more useful in JSF:

  • Using a real Java class instead of declaring interfacing clumsily in XML.
  • The locality principle. The JSF template, the “code behind” class and the CSS class should be in the same folder.
  • Simulating or using the shadow DOM.

There’s already a template language we could use: the JSF facelets. So basically all we’d have to do is to read the template from an unorthodox folder, binding the XHTML template, the CSS file, and the Java bean together, and to make it available as a new JSF tag.

Maybe this is something a component library can do. In any case, it should be a relatively simple extension to MyFaces and Mojarra.

Wrapping it up

I’ve got the nagging feeling that creating components has been considered an expert job in JSF. Angular, on the other hand, forces developers to create components from day one. So the Angular team has optimized the component building until it’s intuitive and fun. The resulting programming style differs a lot.


Dig deeper

Mkyong on creating composite components


6 thoughts on “Why are Angular Components more Successful than JSF Components?

    1. I disagree, and for a good reason. But I also know you and value your expertise. Would you mind to give an example or two? Maybe even a guest post?

      Thanks in advance,
      Stephan

      1. TBH I have always used ui:include instead of composite components. Like Marco says below the only place I had heard about composite components before was through BalusC. After reading your article I tried creating some templates and it seemed a better way than using a ui:include because the parameters can be strongly typed and it almost works like a taglib. I also believed it would solve a problem I had with recursion which has meant that I have to keep using xmlns:c=”http://xmlns.jcp.org/jsp/jstl/core” in my XHTML to prevent loading of includes during build time. So I posted the comment on this article believing it could help me. After some extra time, I realized it had not helped at all and there is still a dependence on JSTL.

        On another note I am subscribed to your blog on RSS but not the comments so I didn’t see your comments before. I will follow the comments now so I can keep up to date.

  1. When you have gotten used to the habit, composite components are incredibly powerful and much more simple than it looks at first. The problem is, that you almost find no good examples besides the most basic ones. When you google for composite components, almost the only realiable resource you find are articles or answers on stackoverflow by balusC. It took years for me to really be get used to it and to remember composite components when thinking about possible solutions for requirements.

    In contrast, components are the bread and butter of every angular2+ application. You can’t get around them so they are much more visible and much easier to implement. But its still a challenge to think in components and to do it right as they are so different compared to a classical MVC application (think: controllers). I think this is (besides others) one of the key points why angular2+ hasn’t gained as much track as before. With frameworks like vue you can hack away in a more classical way and many developers tend to find this easier.

  2. I basically have nothing against composite components (cc), that’s true it’s easy to write, it is actually very tempting to write a lot of composites because it’s so easy to do so, the API looks to cover all the needs but here is the thing: it is very bad supported by JSF implementations. Here is an example: https://stackoverflow.com/questions/15002441/primefaces-outputlabel-for-composite-component I’ve been facing this problem, took me while to understand what was going on but and the fix involves a lot changes but thanks to Leo explanations https://issues.apache.org/jira/browse/MYFACES-4059 I’ve been able to fix it in Primefaces. So first, cc are handled in a very different way than simple component, second they have a significant overhead during building/restoring of the view (specifically: during saving/restoring the view state). I quote BalusC https://stackoverflow.com/a/6822269/4605161

    To make it simple: use facelet tags. Yes it’s older than composites components but they simply work, or as Stephan stated, write your own (even though I think write facelet tags are easier specially if the component only wraps other components)

  3. I’ve found JSF components doesn’t work in many usecases and we’re using facelets components in our project now. It works surprisingly well. What I like on composite components is the separation of component’s properties in interface section. I did a similar separation for facelet components as well. We’re using it for tens components in our project, it works both for mojarra and myfaces (with STRICT_JSF_2_FACELETES_COMPATIBILITY flag). It is published on github now https://github.com/skybber/Tagext.

Leave a Reply

Your email address will not be published.