Pages

Showing posts with label jsf. Show all posts
Showing posts with label jsf. Show all posts

2008-12-22

Hacking the rich:pickList using jQuery

Another post about the JSF 1.2 upgrade.

Short description of the problem:

We had hacked together a custom pick list from before. After upgrading to newest JSF and newest RichFaces, we could use a standard pick list, except that the standard pickList didn't support any means of showing details about the selected item.

We could of course tried to subclass the RichFaces pick list component, but then we would be stuck with maintaining it. So instead we decided to just throw in a quick jQuery script. Of course, it would also be a good opportunity to learn a little more jQuery. (Yes, I've just started learning jQuery, so if you think you've got a better way to solve the problem, please leave a comment.)

Getting an event when somebody selects a cell

<ui:define name="perPageJavaScript">
<script>
jQuery(document).ready(function(){
                jQuery(".rich-picklist-source-cell").click(function () {
                               updateFooBar(jQuery(this).text());
                });
    });</script>
</ui:define>

Using the event to update a part of the page

<a4j:form>
    <a4j:jsFunction name="updateFooBar"
        reRender="fooBarTbl,fooBarBazTbl">
    <a4j:actionparam name="param1" 
        assignTo="#{fooBarBean.selectedFoo}" />
    </a4j:jsFunction>
</a4j:form>

the perPageJavaScript is just a way to insert a custom JavaScript into the header of one particular page.

Hope this helps someone. I guess I'm not the only one who needs this construct.

2008-12-16

Upgrading a JSF 1.1 project to JSF 1.2

I've just upgraded a project from JSF 1.1 (MyFaces) with tomahawk to JSF 1.2 (Mojarra) with Facelets. Halfway through the process I realized it would be worth sharing, since I would have appreciated if somebody else had done that before me. (There is a description about how to make a new project with JSF 1.2 on http://forums.sun.com/thread.jspa?threadID=5156242, but I wanted to upgrade an old project.)

Facelets is XML

Because facelets are xml documents you need to change && in your expression language statements to &amp;&amp; (I found the tip here: http://saloon.javaranch.com/cgi-bin/ubb/ultimatebb.cgi?ubb=get_topic&f=82&t=001835.)

Update 2008-12-23: If you're smart and read the documentation, you might also find out that you can just write and instead of both && and &amp;&amp;.

Also remember that xml comments are written as <!-- --> instead of <%-- --%>

We don't need the tomahawk taglib any more!

While I appreciate the effort that people has put into MyFaces/tomahawk, it also became a major hurdle in the process of upgrading the application. The reason is that it took very long time before the developers announced a JSF 1.2 compatible version, and by that time, I was already decided to get rid of that taglib.

We mainly used to use the tomahawk library for 4 different things:

t::updateActionListener

<t:updateActionListener value="#{fooBean.bar}" property="#{bazBean.bar}" /> can now be substituted with <f:setPropertyActionListener value="#{fooBean.bar}" target="#{bazBean.bar}" /> in the standard f: taglib.

t:dataList

t:dataList can be substituted with rich:dataList

forceId

The components in the tomahawk taglib has an attribute called forceId which overrides JSF's id generation, allowing you to specify the precise id you want for a tag.

There's no such things as a forceId attribute in any of the other taglibs we use, but luckily, with facelets you can now use plain html tags if that is what you want. Also, much of the reason for using forceId was for selenium testing. Later on, I learned that we could use xPaths with selenium to pin down a page element without resorting to the id. (If you decide to try, there is at least two different Firefox plugins that you can use to find the xpaths, and at least one of them is useable, I just can't remember the name.

The last reason for using tomahawk was either the sortable table or the fileUpload component. Luckily, both are easily available in the rich taglib.

http://www.google.com/search?complete=1&hl=en&q=Bean+or+property+class+javax.faces.model.SelectItem[]+for+managed+bean++cannot+be+found.+&btnG=Google+Search&aq=f&oq=

Using arrays in faces-config.xml doesn't work

At least not i mojarra. Here's my changes:

- public SelectItem[] getFooBarOptionList() {
+ public List getFooBarOptionList() {
      List optionList = new ArrayList(FooBazFooBarEnum.values().length);
      for (FooBazFooBarEnum fooBar : FooBazFooBarEnum.values()) {
          optionList.add( new SelectItem(fooBar.getValue(), fooBar.getValue()));
      }
-     return optionList.toArray(new SelectItem[optionList.size()]);
+     return optionList;
  }
  <managed-property>
-   <property-name>fooBarOptionList</property-name>
-   <property-class>
-    javax.faces.model.SelectItem[]
-   </property-class>
-   <value>#{fooBazDetailFilterBean.fooBarOptionList}</value>
-  </managed-property>


<managed-property>
+   <property-name>fooBarOptionList</property-name>
+   <property-class>java.util.List</property-class>
+   <value>#{fooBazDetailFilterBean.fooBarOptionList}</value>
+  </managed-property>

One last thing:

Here's some code to fetch whatever managed bean you need without injection. I don't suggest you should do anything like this, but if you have already done it, and need to upgrade to JSF 1.2, here is how:

From:

public static Object getBean(String beanName) {
    return getContext().getApplication().getVariableResolver().resolveVariable(getContext(), beanName);
}

To:

public static Object getBean(String beanName) {
    return getContext().getApplication().getELResolver().getValue(getContext().getELContext(), null, beanName);
}

Remember: use with caution, as the result may be hard to unit test.

2008-12-09

Going to boot Windows XP on my laptop tonight..

..because I want to test JavaFX while commuting tomorrow.

I've been looking forward to JavaFX because I hope it may put an end to the current misuse of HTML for web applications by people who think that hiding javascript from the developers is a good thing.

2008-11-18

Making a "selectable" list component using facelets

Disclaimer: This is not a defense of jsf. If markup were an animal specie, then using jsf would get you arrested for mistreatment. I'm hoping that JavaFX wil give us a better way to make RIAs.

in web.xml

<context-param>
    <param-name>facelets.LIBRARIES</param-name>
    <param-value>/WEB-INF/somewhere/you/decide/whatever.tablib.xml</param-value>
</context-param>

in whatever.taglib.xml

<?xml version="1.0"?>
<!DOCTYPE facelet-taglib PUBLIC
  "-//Sun Microsystems, Inc.//DTD Facelet Taglib 1.0//EN"
  "facelet-taglib_1_0.dtd">

<facelet-taglib>
  <namespace>http://www.yourdomain.com/anothernameyoudecide</namespace>
  <tag>
    <tag-name>li</tag-name>
    <source>li.xhtml</source>
  </tag>
</facelet-taglib>

in li.xhtml

<ui:composition xmlns="http://www.w3.org/1999/xhtml"
    xmlns:ui="http://java.sun.com/jsf/facelets"
    xmlns:c="http://java.sun.com/jstl/core">
    <c:choose>
        <c:when test="#{selectedPageName == pageName}">
            <li class="#{class} menuItemSelected"><ui:insert /></li>
        </c:when>
        <c:otherwise>
            <li class="#{class} menuItemNotSelected"><ui:insert /></li>
        </c:otherwise>
    </c:choose>
</ui:composition>

(I was particularily impressed to see that I could just add the existing classes as easy as it is done above. It's one of those rare moments when I think that it would be wonderful if it was this simple, -just to find out that it actually is!)

making the menu

<ui:component xmlns:jsp="http://java.sun.com/JSP/Page"
    xmlns:ui="http://java.sun.com/jsf/facelets"
    xmlns:h="http://java.sun.com/jsf/html"
    xmlns:f="http://java.sun.com/jsf/core"
    xmlns:y="http://www.yourdomain.com/anothernameyoudecide"
    xmlns:c="http://java.sun.com/jstl/core">
<ul class="horisontalMenu" id="topMenu">
        <li jsfc="y:li" pageName="home"><a href="Home.faces">#{bundle['topmenu.home']}</a></li>
        <li jsfc="y:li" pageName="search"><a href="Search.faces">#{bundle['topmenu.search']}</a></li>
        <li jsfc="y:li" pageName="reports"><a href="Reports.faces">#{bundle['topmenu.reports']}</a></li>
    </ul>
</ui:component>

setting the selected top menu

easy as just dropping this into the ui:composition of the facelet your displaying:
<ui:param name="selectedPageName" value="home"/>

2008-10-17

So, you're stuck with <insert not so cool technology here>

This is a work in progress. Don't be surprised if this post changes over the coming weeks. This post is about small things you can do, even if you're stuck with whatever uncool technology.

Do something cool while commuting

I personally have spent a almost all my commuting time the last twelve months programming symfony. First a billing system for small businesses and then a web app for organizing work parties. The last one was for a non profit. Not paid of course. But it helps a lot to to something cool for 45 minutes in the morning before you start wrestling obtrusive frameworks that don't even respect basic things like url's. I also believe, out of personal experience, that I arrive at work more fit for work after 45 minutes of doing something cool and relevant, than after sleeping for 45 minutes more.

Use test driven development to save time

When I arrive at work, I can just forget about the comfort of making changes, alt-tabbing to firefox and refreshing to see the changes. There are some smart ways of avoiding server restarts, but the most important trick I've learned so far is to do use tests as far as possible before I deploy to the server and do the final testing. This way I save time, and I avoid sitting and waiting for that server, just to loose the patience and start looking at dzone for something useful. Oh, and then you also have the usual benefits of having a test suite to help you when you find out that you have to refactor that stuff.
Update (2008-10-31): Learn mockito. It is wonderful to just write someComplicatedClass = mock(SomeComplicated.class) instead generating a mock manually.

Refactor that stuff

I've recently read Michael Feathers "Working Effectively with Legacy Code", and it contains a lot of useful hints about how to get your code testable and how to add features in a safe way, but it was first at Robert C. Martin's speech at JavaZone this year that I became really inspired to make existing code more readable. If you've time, watch that presentation. It is available here. He recently published the book "clean code". Guess I'm going to buy the book. Just watching his presentation about functions was enough to go back to work and turn a 1200 line monster class into a much more readable class of less than 500 LOC. And I'm not finished with it yet.

Find some uninterrupted time, any uninterrupted time

(I don't do this anymore. But it worked 2 years ago, before I got married.) Sometimes I've found it better to trade in a couple of hours of sleep for a couple of calm hours. If your day is filled with interruptions, and you don't have a family to take care of, try sleeping a couple of hours (not more) in the afternoon. By the time the interruptions are going to sleep, you are (hopefully) wide awake and ready to get some real work done. Uninterrupted. And since you're not paid for it, you decide what to prioritize. In the morning, you might find it useful to sleep a couple of hours again, just so you can stay awake the rest of the day.

Update: Learn The Pomodoro Technique

(2008-10-31)I have just started learning "The Pomodoro Technique" and, so far, it has been a very interesting experience. Basically it helps you staying focused and avoid internal and external distractions. Add to that that you could learn the basics in less than one hour, and that you don't have to convert your whole team to increase your own productivity.

Update: Get a headset

Headsets serve two purposes:
  • Inform coworkers that you're trying avoid beeing interrupted
  • "Mask" conversations to avoid beeing distracted.

You found out something useful? Blog about it

How many times have you searched for something just to find the answer at someones blog? If you've had a hard time finding out something, chances are that someone else on this planet is wondering about the same. An example: I recently had a lot of work to remove a trojan until I did a search on google for information updated last 30 days about tdsserv. It turned out to be a very new trojan, first observed around 15. of september, as far as I understood the information. I posted the solution to my blog, hoping that someone else might find it useful, too. Last time I checked, I had three results coming in from search engines, related to that post, so obviously, I was not alone. It won't get me rich, but at least I'm sharing back.

2008-09-21

About Java, closures and attracting new developers, part II

(Warning: A web developers perspective.) I've been thinking of this since I wrote the post: About Java, closures and attracting new developers, where I tried to prove that the problem with Java is not related to the lack of closures. At the risk of offending the rest of you, here comes my explanation of why I don't use Java for my spare time projects, even if I like it.
  • The web server (I mostly use tomcat 6 at work) takes to long time to restart, so long time that it quickly becomes painful, especially when you add to this that:
  • you have to restart it every time you've changed a class.
  • The recommended web framework, JSF (JavaServer Faces) doesn't care about URLs. By default it will show the URL from the last page you visited.
  • JSF has a really unnecessarily complicated template language. I mean, I can't see the reason for having to use <h:panelgrid> when what you wanted is just <table>. Not to mention that there is no <div> tag in the default component set. Of course, you can just use a component set that has one, (or make your own if you have a couple of hours to spend,) but I guess you see my point.
  • JSF messes around with my id's, even if I've not asked it to do that. To get around that limitation you once again has to use a different component set (tomahawk comes to mind).
  • You don't have access to the javascript that is used. Of course this is touted as a benefit of using JSF, but in my opinion it's just a horrible violation of the rule about separation of concerns. What happens is that you can't just include that standard well-tested javascript library you want, which means you have to use jsf components again. And guess what: Those components are broken, and it always ends up with a lot of extra work for the designer.
  • And of course: JSF isn't the only problem with Java. Take something as simple as how to print a line of text to the console: "System.out.println()", or think about trying to open a file for reading. With execuse to every swede who reads this, we have a childish joke here in Norway that goes like this "How many swedes do you need to change a light bulb?" The answer is 1000, one to hold the bulb, and 999 to turn the house around. Same goes for Java, - how many objects do you need to read a file line by line? Or to resize a picture? (Yes, I know Fabrizio Giudici has tried to defend it, but I do not agree. Often, the Java API's seems way to low level, and my feelig is that sometimes you have to use one factory class on top of another. Also see next point on why this is more of a problem than it could have been.)
  • The documentation is also painfully unbalanced: There is a lot of javadoc generated API documentation everywhere, but I can't think of a single place to find something like askeet, -a well thought out demonstration of how to use the api or framework your're providing. (OK. I can remember to have seen som interesting blog posts over at http://weblogs.java.net. Example.)
But yes, I still use Java at work. And I still think Java is a great language, and a great platform. It just lacks a good, full stack web framework with great documentation, running on a fast server that doesn't need to be restarted many times an hour. (Edited: 2008-09-30)

Updated 2008-12-14: Symfony has done it again! More documentation available here: http://www.symfony-project.org/jobeet/1_2/Propel/en/

2008-08-18

Had a really strange problem with JSF before the weekend. A command button was supposed to save the form, but instead, the page would just rerender, as if it failed validation. It turned out to be just an ordinary null pointer exception, but it took some time to realize that because no stack trace showed up, and the h:message box was empty.

I guess sooner or later someone will search for this problem, so here is the post I found that solved it: http://forums.sun.com/thread.jspa?messageID=3263230  . I had to change it a little to get it to work, but I guess those changes has disappeared since then. (Of course I didn't submit those changes, as they were just for debugging.)

(Yes, someone is going to search for what you just found out, so you better start blogging now. Big thanks goes to everything is Broken for sharing how to get the Trust Flat Scan USB 19200 working under linux.)