Building Custom JSF UI Components

Home

News: Building Custom JSF UI Components

  1. Building Custom JSF UI Components (34 messages)

    Building custom JSF UI Components is a fairly straightforward process. Once you understand the mechanism detailed in the encode() and decode() methods in the rendering code, the rest is a fairly trivial process of providing the necessary "plumbing" with tag handlers as such to enable usage in a typical client such as a JSP based client. In this article, Chris Schalk walks readers through creating a new JSF component - a "Hello, World" component at first, becoming a stock price component in the end.

    Read Building Custom JSF UI Components

    Threaded Messages (34)

  2. This article is an excellent introduction to making simple components in JSF.

    For comparison, however, here is the equivalent Tapestry implementation of that component:

    StockInput.html
    The StockInput Component:
    &ltinput jwcid="@TextField" value="ognl: symbol"/>
    &ltinput jwcid="@Submit" label="Enter Stock Symbol"/>
    &ltspan jwcid="@Conditional" condition="ognl: symbol">
        &ltp>The current price for &ltspan jwcid="@Insert" value="ognl: symbol"/> is:
        &ltspan jwcid="@Insert" value="ognl: price"/>
    &lt/span>

    StockInput.java
    @ComponentClass
    public abstract class StockInput extends BaseComponent {
      public abstract String getSymbol();
      public String getPrice() {
        // The Web Service code to get the price of getSymbol()
      }
    }

    That's all of it. Enjoy.
  3. Building Custom JSF UI Components[ Go to top ]

    ...That's all of it. Enjoy.

    You actually need a little more than that I believe, such as creating a ".jwc", a ".page".. etc but thanks for the compliment. :)

    Keep in mind that my article shows all the moving parts including registering the component etc..
    Also, I showed how to build components for use in JSP which necessitates a custom JSP taglib. For non-JSP usage of JSF components, this is not required. Similar to your example, in the simplest case, a JSF component can just be a class with code to render itself.

    I'd be interested in an any complete article that shows the whole story on how to build Tapestry components with all config details.. I'd be happy to return the compliment. :)
    -Chris
  4. Building Custom JSF UI Components[ Go to top ]

    One thing to note, and maybe it's just personal preference with component development is that for testability and reuse, you externalize stock logic to a POJO bean-- not a component. So you have your component-- or template-- that isn't associated with a Java instance, and then have a POJO that can be allocated via bean management (either Hivemind, Spring, or JSF).

    my.taglib.xml
    <tag>
      <tag-name>stock</tag-name>
      <source>/facelets/tags/stock.xhtml</source>
    </tag>

    stock.xhtml
    <ui:component>
      <form jsfc="h:form">
        <input type="text" jsfc="h:inputText" value="#{stock.id}"/>
        <input type="submit" jsfc="h:commandButton"/>
      </form>
      <span jsfc="c:if" test="#{stock.value}">
        Your whatever is #{stock.value}.
      </span>
    </ui:component>
  5. Building Custom JSF UI Components[ Go to top ]

    You actually need a little more than that I believe, such as creating a ".jwc", a ".page".. etc
    You do not actually, not in Tapestry 4.0 :) Not even if you have some more complex, such as component parameters, for example. The Java file and the template are just enough.

    I think a similar article about development and configuration of a Tapestry app is a very good idea. I do feel that what you have done about JSF is pretty good though.


    A sidenote: earlier I missed semicolons and the html file was quoting badly. Here it is again, this time quoted properly:
    The StockInput Component:
    <input jwcid="@TextField" value="ognl: symbol"/>
    <input jwcid="@Submit" label="Enter Stock Symbol"/>
    <span jwcid="@Conditional" condition="ognl: symbol">
        The current price for <span jwcid="@Insert" value="ognl: symbol"/> is:
        <span jwcid="@Insert" value="ognl: price"/>
    </span>
  6. Building Custom JSF UI Components[ Go to top ]

    I think a similar article about development and configuration of a Tapestry app is a very good idea. I do feel that what you have done about JSF is pretty good though.

    Thanks again for the compliment and the updated Tapestry 4.0 info... I was going off 3.0.2.

    -Chris
  7. You do not actually, not in Tapestry 4.0 :) Not even if you have some more complex, such as component parameters, for example. The Java file and the template are just enough.I think a similar article about development and configuration of a Tapestry app is a very good idea.

    Well, perhaps you could write such an article?
  8. The JSF component model[ Go to top ]

    Is complex compared to something like tapestry.
    But the cause of this is rather simple, JSF is a general framework for server side rendered uis, thus you can write renderers for VT220, or for Swing or whatever....

    There are easier componentization mechanisms than writing a full blown jsf component as long as you stay in the HTML realm.

    Myfaces has the alias beans which are even simpler than the tapestry example, but they lack controller bindings,
    then there is the good ole Tiles which is ported over from struts, and then there are facelets, which are not limited by HTML...
  9. additional note[ Go to top ]

    I also forgot, pure client side is relativ only, even plain html sites are basically built on the server, the client basically just gets a markup file and renders it.
    So everything has to be performed on the server anyway, but it is how you do things, do you just do markup templating or do you use the dynamic code behind it to do the rendering for you.
    But that is not the main problem, the main problem is the increased complexity caused by the mix of taglib, controller, view, model mechanisms and bindings over xml, which is simplified by Shale Clay, Facelets and other approaches.

    The compariso to Tapestry and other rather simple componentization frameworks is not really that valid, all those frameworks limit themselves to html or html like markups and some of them do not even have a full event system and a controller logic behind it.
    Those frameworks do their jobs very well in a pure html domain, however, but once you have worked with a good event system you do not want to go back to the plain render submit cycle anymore.
  10. additional note[ Go to top ]

    The compariso to Tapestry and other rather simple componentization frameworks is not really that valid, all those frameworks limit themselves to html or html like markups
    Why do you call them 'simple'? Have you even looked at Tapestry, Wicket and Echo? I hardly call those frameworks simple. They make application development simple, which JSF can't deliver without drag'n'drop tool support and (according to the JSF incrowd, I haven't confirmed this) the recent addition of JSP 2.x and facelets.

    Even though I've yet to find my first customer that requires the same front end to render in both HTML and WML, Wicket and Tapestry allow for WML and/or VoiceXML extensions. There is absolutely no reason why they couldn't support those 'renderings'. There only hasn't been an interest in that technology.
    and some of them do not even have a full event system and a controller logic behind it.

    Names please? Generalizations like this are very common place in these discussions. I'd like to know how you come to such a conclusion and which frameworks you refer to. It seems like you are talking about different frameworks than Tapestry and Wicket here.
    Those frameworks do their jobs very well in a pure html domain, however, but once you have worked with a good event system you do not want to go back to the plain render submit cycle anymore.

    I think you've got your frameworks mixed up. Are you sure you are talking about Wicket and Tapestry here?
  11. additional note[ Go to top ]

    Why do you call them 'simple'? Have you even looked at Tapestry, Wicket and Echo? I hardly call those frameworks simple. They make application development simple, which JSF can't deliver without drag'n'drop tool support and (according to the JSF incrowd, I haven't confirmed this) the recent addition of JSP 2.x and facelets.

    Again, JSF is big enough that there's lots of opportunity to only make things easier. And I mean it. I wrote Facelets in June/July and aside from a few bugs here and there, no one has needed any additional features.

    Now, this doesn't cure component development. Well, frameworks like Clay and Facelets throw the need for component development and just base development on composition.

    What's next? Well I have a project running on my machine that uses annotations for JSF component development... backed by CGLIB to take a lot of the grunt work out of state managmenet while still leaving JSF's flexability in rendering and behavior.
  12. additional note[ Go to top ]

    Hi Jacob,

    I am not sure whether you realize it, but you have just written yet another "Just wait some more!" message.

    You see, I have been using Tapestry for an easy component web development since 2001 -- proper encapsulation, excellent separation between developers and designers, etc.

    In that time we first heard "Just wait until JSF comes out!". Then it was "Just wait some more!" because of the delays. When it eventually came out, it did not match the expectations (I remember an article titled "That was it?"), and people said "Just wait some more until it has components!". Then it was "Just wait some more until the templates are fixed!". Now it is "Just wait some more until component development is easier!". What's next? I am guessing it would be something like "Just wait until JSF performs well!". Ad infinitum.

    You see, I have had all of those things with Tapestry since 2001 and I am consistently getting much more with that framework -- features that JSF will not provide anytime soon. The code above is just a simple example of how easy everything is with Tapestry.

    There are some good moves in the JSF world, individual efforts such as the Facelets library. But that is far from enough, as you have indicated yourself. And if the past is a sign of the future, well...
  13. additional note[ Go to top ]

    Mr. Bridge ;-)

    You are totally right about where JSF is at. You can blame too many roosters in the hen house or the JCP process, but with attempting to push a quote unquote 'standard'-- everyone must be taken into consideration and their needs which slows innovation.

    Again, JSF is big enought that it can only be simplified at this point. You guys were able to jump right on to JSE 5 with annotations while we were working through JSP integration issues for JSP. JSF is now a 'solid' platform because of it and to sound like a broken record, you will be seeing us now concentrate on ease of development. The foundation is now there, we know what works under the hood. Now we need to do a better job of providing the little mod-kits and add-ons to this vehicle with JSF 2.0.
  14. additional note[ Go to top ]

    JSF is now a 'solid' platform because of it and to sound like a broken record, you will be seeing us now concentrate on ease of development. The foundation is now there, we know what works under the hood. Now we need to do a better job of providing the little mod-kits and add-ons to this vehicle with JSF 2.0.
    Does a modded Cavalier drive better than a stock MR2? Or maybe it looks better? Or has better mpg? Or is easier to repair? At least it runs on regular, parts are dirt cheap and there are a lot of repair shops that can fix the damn thing. People in the shops are employed, people making parts are employed, economy is blooming.
  15. additional note[ Go to top ]

    one follow up as an example...

    Developers have a lot of options with the JSF stack over getting 'one' solution with Tapestry. Good or bad, the JSF stack has opportunity to evolve at different levels with your needs. I *could* use Oracle's ADF component library with AJAX support, within Facelets, and then use Struts Shale as a controller, and then back all EL use with both Hivemind and Spring. Over the top? Maybe. But like I said, the opportunity is there.
  16. Isn't it a possibility that because Shale/Clay/Facelets are needed, it means that JSF is lacking at best? And usually stacking such a load of technologies to make something work, is an antipattern.

    Giving developers too many options (to do the same thing, that is) is not per se good design. It completely the oposite of 'do one thing only and do that good'. Or do the simplest thing that could possibly work. Or KISS...

    Wicket tries to solve one thing good, and make it simple, and thus the obvious choice. If you wish to do it another way, then we try to give you as much flexibility as possible, without exposing our guts and making it hard to do your thing.

    We think that 80% of development with Wicket should be easy as can be, and we choose always defaults and provide helpers to enable this. The other 20% is catered to as well, but it is just a little harder than the 80% that is common. This has worked well so far, as:

    Wicket is the most recommended framework.

    Appologies for the wicket spam, but I couldn't help myself.
  17. Martijn, I wouldn't apologize, you brought up some good points.
  18. Isn't it a possibility that because Shale/Clay/Facelets are needed, it means that JSF is lacking at best?
    JSF is a standard! It's like saying that if Servlets were complete we wouldn't need Tomcat/Resin/Jetty. If too many options is bad, too few is even worse! Competition is a major push for better products.
    And usually stacking such a load of technologies to make something work, is an antipattern.Giving developers too many options (to do the same thing, that is) is not per se good design. It completely the oposite of 'do one thing only and do that good'. Or do the simplest thing that could possibly work. Or KISS...Wicket tries to solve one thing good, and make it simple, and thus the obvious choice. If you wish to do it another way, then we try to give you as much flexibility as possible, without exposing our guts and making it hard to do your thing.We think that 80% of development with Wicket should be easy as can be, and we choose always defaults and provide helpers to enable this. The other 20% is catered to as well, but it is just a little harder than the 80% that is common. This has worked well so far, as:Wicket is the most recommended framework. Appologies for the wicket spam, but I couldn't help myself.
    I am too a Wicket fan, but standards are needed. And standards should be general and not specific, that's why we don't get nice defaults and all, instead JSF implementations should aim for that, that's why Shale/Facelets/others must exist.

    Regards,
    Henrique Steckelberg
  19. additional note[ Go to top ]

    They make application development simple, which JSF can't deliver without drag'n'drop tool support and (according to the JSF incrowd, I haven't confirmed this) the recent addition of JSP 2.x and facelets.

    If you had really listened to the 'JSF in-crowd' you would not have posted that JSF can't deliver simple application development without tool support. I don't understand why this myth persists. Many of us work with JSF with no tool support, no drag-and-drop, yet find it simple and powerful. Sure, it has flaws, but requiring tools is not one of them.
  20. additional note[ Go to top ]

    Many of us work with JSF with no tool support, no drag-and-drop, yet find it simple and powerful. Sure, it has flaws, but requiring tools is not one of them.

    Sure. You can hand code your EJB's too. Now, /that's/ fun.
  21. for the sake of completeness[ Go to top ]

    It's even simpler with wingS:
    class StockForm extends SPanel {
        public StockForm() {
            super(new SGridLayout(2));
            final STextField text = new STextField();
            SButton button = new SButton("enter stock symbol");
            add.addActionListener(new ActionListener() {
                public void actionPerformed(ActionEvent e) {
                    addStockSymbol(text.getText());
                }
            });
            add(text);
            add(button);
        }
    }
  22. Compilation error :-)[ Go to top ]

    Compilation error: undefined symbol 'addStockSymbol'

    I think that function does more than getting the price for IBM...

    So it is still not complete ;-)

    I don't think the point of the article is to get at which framework 'has the shortest' (strange analogy) but that it is relatively painless to create custom components in JSF, in contrast to the general opinion.

    I think that Chris made that quite clear, eventhough it may not be what (Tapestry|Wicket|WingS|...) developers want. When compared to other frameworks out there, JSF still has enough improvements to make in the developer friendliness of things, but at least Jacob is committed to do so.

    Go Jacob (and others)!!!
  23. Before showing how to build a "Hello World" custom component, let's review quickly how to use it. To invoke the component we have a JSF enabled JSP page with an extra taglib directive specifying a custom tag library (tld) which contains the custom tag, "jsfhello", which is associated with our custom UI Component. To use the jsfhello tag, we simply place it into the body of the JSP and set an optional "hellomsg" attribute.
    How JSF components are packaged? Just as custom tag library?
    For our HelloWorld example, our UIComponent will extend the UIComponentBase abstract class, which is provided in the JSF specification, and render a formatted HelloWorld message. Note: We could have also based our new UI Component class on the concrete UIOutput base class which is basically the same as the UIComponentBase with the exception that it has a "value" attribute. Since we aren't using one, we'll simply base it on the UIComponentBase abstract class.
    Is it possible to use an interface instead of extending a base class? Is it possible not to use ResponseWriter? Is it possible to pass parameters to encodeBegin(), so one could use any arbitrary tag instead of hardcoded one ("H3" in the example)? Is it possible to use several instances of one component on one page? If I want to use WML renderer instead of HTML renderer, do I need to build another component, or I can switch renderers within one component?
  24. If I want to use WML renderer instead of HTML renderer, do I need to build another component, or I can switch renderers within one component?


    Yes! Good question.. The helloworld example shows how a component can do the rendering itself, but the really cool part about Faces is that you can separate the rendering from the component itself using separate renderer classes or renderkits which are families of renderers.

    Oracle's ADF Faces has built-in rendering for different client types.. HTML, WML and even telnet.. :)

    -Chris
  25. Michael, I will try to answer your questions here:
    How JSF components are packaged? Just as custom tag library?
    JSF components are mapped ID -> Class type in a faces-config.xml and then base JspTags are provided for creating a TLD. This second part is only required for JSP use.
    Is it possible to use an interface instead of extending a base class?
    JSF is interface based, but there's a lot of functionality to components that it's better to extend the base class and override with your own behavior.
    Is it possible not to use ResponseWriter
    Yes, your components don't have to render themselves and they can still take part in the full request/response lifecycle.
    Is it possible to pass parameters to encodeBegin(), so one could use any arbitrary tag instead of hardcoded one ("H3" in the example)?
    JSF Components have a zero to many relationship with Renderers. So any component (even default ones) can delegate rendering to an external Renderer. You can even take a UIData component (a table) and only provide a custom Renderer to display the UIData however you want. I think Matthias from MyFaces is working on a generic Velocity Renderer.
    Is it possible to use several instances of one component on one page?
    Yes, a gazillion times if you want.
    If I want to use WML renderer instead of HTML renderer, do I need to build another component, or I can switch renderers within one component?
    Like I wrote above, a given request to JSF is associated with a Renderer ([X]HTML by default) but it could be swapped to Laszlo, XUL, SVG, WML, etc. The only thing you have to provide is a Renderer. Renderers are mapped just like components such that you have a Renderer-ID to Renderer Class, which also includes a RenderKit type such as WML or HTML. So you could develop a single JspTag that requires a component-id and a renderer-id that can be tied to any content type, allowing you to render the same JSP over HTML or WML.
  26. Chris shows the "classical" approach how to create JSF components. It is pretty good if your final destination is creating a component library. However, how the practice says, project developers rarely create the components that are specific for the particular project. Especially, if we speak about composite components. The "Classical" approach is not suitable very well here, it presumes a lot of hardcodding in java.
    As an alternative, there are two very well designed technologyies already exist. Those are Facelets and Shale Clay. They allow to create composite components without java-code and writing tld files at all.
    When JSF 1.2 and JSP 2.1 appear on the scene, the new potential approaches will appear (JSP fragments etc.).
    Probably, the "classical" has a chance to live in the future if it is supported by tools. I guess, Oracle has some fresh ideas around it as soon as this article has been written :-)

    --
    Sergey : jsfTutorials.net
  27. The article is great, kudos, Chris!

    I think the enormous effort needed to build such a (pretty simple) component with JSF 1.1 technology is why it has been so slow in gaining adoption. It is too complex.

    I can only applaud the current efforts in simplifying the development of custom JSF components and JSF applications. I haven't looked at facelets and JSP 2.x, but they sound promising.

    Perhaps when JSF 2 comes out, Wicket and Tapestry won't be needed anymore, or will be used as view technologies for JSF (or vice versa).
  28. StockQuote in Wicket[ Go to top ]

    The most simple way of creating a Wicket component that shows the stock quote from a web service is:

    public class StockQuote extends WebComponent {
    public StockQuoteLabel(String id, String symbol)
    {
    super(id, new Model(symbol));
    }
    protected void onComponentTagBody(final MarkupStream markupStream, final ComponentTag openTag)
    {
    replaceComponentTagBody(markupStream, openTag, getQuote(symbol));
    }
    private String getQuote(String symbol) {
    // do SOAP thingy
    }
    }

    Using this in any Wicket page will be as simple as:
    <span wicket:id="stockIBM">123.12</span>
    <span wicket:id="stockSUN">123.12</span>
    <span wicket:id="stockRHAT">123.12</span>
    And in Java:
    add(new StockQuoteLabel("stockIBM", "IBM"));
    add(new StockQuoteLabel("stockSUN", "SUNW"));
    add(new StockQuoteLabel("stockRHAT", "RHAT"));


    Nothing else is needed. No registration of components, no annotations, no XML, no 'remember to', just Java and HTML.

    I'll create a blog article later tonight with the full details.
  29. StockQuote in Wicket[ Go to top ]

    Apparently it is bad karma to have a 13th post...

    Missing 1 line of code in the onComponentTagBody method:

    insert before 'replaceComponentTageBody' the following line:

    String symbol = getModelObjectAsString();
  30. Try this:

    public class StockQuoteLabel extends Label
    {
      public StockQuoteLabel(String id, final String symbol)
      {
        super(id, new AbstractReadOnlyModel()
        {
          public Object getObject(Component component)
          {
            return soapThingy(symbol);
          }
        }
      }
    }

    I haven't tested this, but it should work fine and it's not involved in gory details.
  31. Building Custom JSF UI Components[ Go to top ]

    As far as I understand about JSF is it is running in server.
    I'd like to know is "Why do we have to generate HTML components with JSF from server? We still can do it in client side?".
    I am just a novic.
  32. Why[ Go to top ]

    The reason for this is, because it is not html only... that means once you introduce pure client side componentization you basically nail yourself onto one technology while in a pure server approach the renderers can be changed on the fly on a component level.
    Also with a pure client approach you have a hard time adding an event system and a controller view model architecture to the mix.

    Once you omit the thinking you want to be flexible on the frontend architecture and want to go pure html things become way simpler, there are various helpers you already can use to trim down the complexity (shale clay, etc.. all have been mentioned)

    Also there are various shortcuts, you basically can omit the distinction between controller and view and mix the rendering directly into the controller logic, thus you save lots of config file entries and a separate renderer class, I am not sure if you also can mix controller->view->taglib, because the taglib definitions are there to connect jsf with the existing taglib system (which is not needed for vt220 rendering for instance)
  33. sorry[ Go to top ]

    My point was not flaming, but that some of the complexity is there, because JSF goes far beyound pure HTML rendering, with basically building a full UI system which is similar to rich client UI systems, but is suitable for server side rendering, which happens often, Wicket and others limit themselves very strongly to the needs of html, and thus can and are simpler for componentization.

    But as you said, JSF development once you have a set of good tools and a good set of rich client like custom controls can and is very fast, and the component sets slowly but surely arrive, MyFaces already covers most aspects you need for the average webapp, with the Tobago component set, which is OSSed while I write this it becomes even better.
    All JSF needs as a good mechanism for easy layout componentization and that is there via various mechanisms, which are all mentioned.

    I dont want to downplay the other frameworks, they are all good but they cover an entirely different domain of development.
  34. Standards are definitely needed[ Go to top ]

    Look how long Struts has been the defacto standard, and then look at the tool situation, now we have JSF and within one til two years the 1.0 has been finalized good tools which ease development a lot have been popping out left and right and have reached a very mature status.

    I think the JCP currently has the right approach, let the other frameworks be the testing ground of new concepts and once they are established we will look at them and see how we can integrate those into official standards.

    JSF was not the beginning (webobjects was or struts) of web frameworks, and it is not the end, but it is good to have a solid middleground which can be covered by tools and is stable.
  35. The point[ Go to top ]

    Of the article was not to find a shortest route for a jsf component, if you wanted to do that, you only would have had to implement the tag and omit the component part and the renderer part and render straight into html over the tag, but to give a description on how to do properly so that you do not lose flexibility.

    As for tool support, tool support is not needed and even without tools JSF is miles better than many frameworks I have worked with, including struts. It probably wont beat withou tools the more targetted frameworks which render straight into html, but the situation becomes better by the minute.

    And with good tools it is close to heaven, you basically get a rich client ui functionality on to of a server side rendered framework. With all the constructs you constantly would need for a decent UI and which HTML cannot deliver decently. Good extensive components (have you ever had a look at the newly released Tobago component set, a realy ui event system, a more than decent pageflow system, a somewhat basic inversion of object control system, and various rendering systems so that you can reuse most parts of your code if you have to move out of the html realm. And of course lots of tools.

    The few problematic points have been addressed already by a handful of opensource frameworks. The small component set has been addressed by Apache MyFaces and the soon to be MyFaces Tobago components, by Oracle with their ADF faces and a bunch of others.

    The somewhat problematic complexity behind the component model has been addressed by facelet, which adds WebObjects Tapestry ease of use for template components to the mix if you are not heavily in need for different renderers, and the lacking toolset in the beginning has been addressed by pretty much almost every vendor except Microsoft, because they finally have a standard on their hands and can adjust the tool to the standard.

    I am not sure why the constant JSF bashing is going on on theserverside, JSF is a solid foundation and is easy to use and has a lot of things going on which are interesting. You cannot expect from a standard to have the latest and greatest new ideas integrated at V 1.0 that is not the aim of a standard. The aim is to integrate proven ideas into a solid base where the tool vendors and developers can rely upon.