Tuesday, December 21, 2010

JSF2.0 component for cross-field validation


Have you ever had problems with cross-field validation in JSF? Me too, so I created this component. You can validate few UIInput components and have their values as List in validator. The component is in softwaremill-faces library. To use it in maven project, add repository:

<repository>
  <url>http://tools.softwaremill.pl/nexus/content/groups/smlcommon-repos/ </url>
  <layout>default</layout>
  <releases>
    <enabled>true</enabled>
  </releases>
  <snapshots>
    <enabled>true</enabled>
  </snapshots>
</repository>
and dependency:
<dependency>
  <groupId>pl.softwaremill.common</groupId>
  <artifactId>softwaremill-faces</artifactId>
  <version>43-SNAPSHOT</version>
</dependency>
Now you can use multiValidator component. First add namespace to your .xhtml page:
xmlns:v="http://pl.softwaremill.common.faces/components"

Then just wrap components you want to cross-validate in <v:multiValidator>. If you attach validator to this component, value parameter that goes to validation method is List of values of UIInput components inside  tag.

E.g. if you want to validate two checkboxes. Each can be checked or unchecked, but at least one has to be checked.
<v:multiValidator id="multi" validator="#{bean.validationMethod}">
  <h:selectBooleanCheckbox value="#{bean.check1}" />
  <h:selectBooleanCheckbox value="#{bean.check2}" />
</v:multiValidator>
<h:message for="multi" />
Validation method in bean:
public void validationMethod(FacesContext context, UIComponent component, Object value) {
  List<Object> values = (List<Object>) value;
  //value is list of values of both selectBooleanCheckboxes
  Boolean firstChecked = (Boolean) values.get(0);
  Boolean secondChecked = (Boolean) values.get(1);

  if (! (firstChecked || secondChecked)) {
    Message message = new FacesMessage(FacesMessage.SEVERITY_ERROR, "Check at least one checkbox", null);
    throw new ValidatorException(message);
  }
}
If none checkbox is checked error message is displayed in <h:message for="multi"> tag.

Source code of this component is on github.

Any suggestions, opinions or questions regarding this component are welcome. Have a good time using it :)

Tuesday, November 2, 2010

GWT table row as UiBinder

Some time ago I wanted to dynamically add rows to a table in GWT, but I wanted to define row template using UiBinder. Programatically it is no problem. You can create FlexTable and add widgets to it. The problem arises when you want to do it using UiBinder. You can create a FlexTable in UiBinder, and you can create widgets, but you can't create element which renders to html tag <tr>. Kazik Pogoda found a way to do it.

First we need two widgets which renter to <tr> and <td>. The code for TR:
public class TrElement extends ComplexPanel {
  private TableRowElement tr;

  public TrElement() {
    Document doc = Document.get();
    tr = doc.createTRElement();
    setElement(tr);
  }

  @Override
  public void add(Widget child) {
    add(child, (Element) tr.cast());
  }
}
The TD is analogous, just change TableRowElement into TableCellElement and doc.createTRElement() into doc.createTDElement(). We can now create UiBinder xml file which renders to single table row (TR element is it's root):
<!DOCTYPE ui:UiBinder SYSTEM "http://dl.google.com/gwt/DTD/xhtml.ent">
<ui:UiBinder xmlns:ui="urn:ui:com.google.gwt.uibinder"
      xmlns:g="urn:import:com.google.gwt.user.client.ui"
      xmlns:my="urn:import:pl.my.gwt.client">
 
  <my:TrElement>
    <my:TdElement>
      <g:HTMLPanel>
        <g:Label ui:field="icon" styleName="Icon"></g:Label>
        <g:Label ui:field="title" styleName="Title"></g:Label>
        <g:Label ui:field="description" styleName="Description"></g:Label>
      </g:HTMLPanel>
    </my:TdElement>
    <my:TdElement>
      <g:Label ui:field="price" styleName="Price"></g:Label>
    </my:TdElement>
  </my:TrElement>
</ui:UiBinder>
Here is how we can use it to add to a table (FlexTable):
TableRowView trView = new TableRowView();
table.getElement().appendChild(trView.getElement());

Saturday, October 30, 2010

Warsjawa 2010. Impressions.

My impressions after this year's Warsjawa are very positive. Well, in fact I could expect this :) Presentations were interesting, meeting other IT people is always good too. I met Bartek Zdanowski, who wanted to meet me. It's quite strange feeling when you meet somebody who knows you, but didn't meet you before. Strange but nice :)

First presentation was about Play framework by Wojciech Erbetowski. I was a little late, but I've seen enough to notice that Play is framework different than all the others.

I was a bit disappointed that Sławek Sobótka didn't make it there (he fell ill). He's topic was the most interesting for me. However, Paweł Lipiński worthily replaced him. Paweł was talking about what in programming he was taught by... his own children, kindergarten, Roomba etc. I never noticed that when there are 2-3 people in a project, it is much cleaner, but it's becoming a mess when there are more than 5 people. I never noticed it, but now it's very clear to me. It seems Paweł is a man who can learn and get knowledge from anything. Ah, and he mentioned me :)

This year on Warsjawa there was also something from our Szczecin JUG. Darek "Lock" Łuksza presented Git version control system and it's Eclipse plugin EGit. Darek did great job, and even found one bug during presentation :) It seemed a bit embarassing for him, but the rest was very good. He knows the topic very well (he's EGit commiter) and he showed many things coding live. Overall presentation was very good.

After Darek's presentation pizza arrived. It disappeared quite quickly, maybe there was a bit too few. We run out of beverages too. Anyway I didn't hear somebody died of hunger or thirst, so it wasn't that bad :)

Next interesting presentation was about Clojure. This time there were two presenters. First Marcin Rzewucki showed us some theory, then Jan Rychter told about practical use of Clojure in Fablo. He showed few interesting features of this language, like STM. Thanks to STM in Fablo they are able to replace customer's database without stopping the service. Pretty impressive.

Did you know that in Java you can have two methods with the same name and arguments, differing only by return type? Compiler can't compile this, but if you write it in bytecode it is perfectly valid! This and others interesting things about bytecode were shown by Adam Michalik. I wonder if any company needs "bytecode programmer"? I like such low-level stuff. At the university I always liked assembler.

The last presentation by Rafał Rusin was about Apache HISE. I have to admit I was too tired and the topic was not very interesting for me, so I didn't remember much from this one.

Generally I think this was very nice conference. Meeting new people, and some older friends, is always nice. Listening to interesting people talking about interesting things is also nice. It seems one hour for presentation is very good duration. All the presenters could do all they wanted/needed (at least it seemed so). I remember on GeeCON there was only 45 minutes and it was too little. If only there was more pizza (or maybe something better?) and beverages it would be perfect.

Wednesday, October 13, 2010

Convert JME application to Android

Here is the story:

I bought Android phone. Earlier I was using Windows Mobile phone, and I had one j2me application on it that was very important to me. It was "TokenGSM", application which serves the same purpose as RSA tokens, but installed on my phone. Very good decision of my bank that they created it so users don't have to carry additional device with them (users have choice, you can also get RSA token if you prefer it). So this application is necessary if I want to log in to my bank account. Pretty vital.

But, as you probably know, there is no Java ME on Android :( Here is what I did (this forum was useful):


  1. Call the bank and ask for new GSM token. Token is somehow bound to the phone, so if you change phone, you need new token.
  2. Write down URL from WAP Push SMS. Do it before opening it. On my phone (Android 2.2, HTC Desire) if you don't do it but just try to open URL, it's lost. Browser can't open it, but you don't even have chance to see it. Browser just blinks and returns to home screen :| It's not in history, nor in downloads.
  3. Go to http://www.netmite.com/android/ and download App Runner. I went there from my phone and downloaded directly to it. I'm not sure if this point is really necessary, but some say it is.
  4. Click "Convert existing j2mes into apk & upload to Android Market." I don't think it really uploads to Market.
  5. Enter your written down URL and click "Get Apk". You have your Android TokenGSM :)
  6. Transfer the file to your phone and install it.
  7. Now you have to activate the token with code you received from the bank.

Sunday, September 26, 2010

Flash scope in JSF 2.0 (nothing about Adobe Flash)

In JSF 2.0, amongst Request, Session etc, there is the new scope called Flash. (However there is no annotation @FlashScope, and you can't put bean in this scope). It's concept is taken from Ruby on Rails. Data in Flash scope are available for current and for next request, but not for subsequent requests. Usage is very simple.
On first page (e.g. index.html):
<h:form>
  <h:inputtext value="#{flash.text}">
  <h:commandbutton action="page?faces-redirect=true" value="To page">
</h:form>
And this is the page we are redirecting to, page.xhtml:
<h:form>
  <h:outputtext value="#{flash.text}">
</h:form>
Why would you need such scope? Imagine you want to enter data on one page, then redirect to another page, and display this data. If not for redirect, we could use Request scope. But with redirect value is sent with request, then browser is redirected to another page, and makes another request. Request scoped value is gone. In such case Flash scope becomes useful. We can put value in this scope with one request, and when another request is made, the value is still there. But it is not stored in session, and is not available for subsequent requests.

However, there is a way to make data in Flash scope alive a bit longer. It is enough if in page.xhtml we change #{flash.text} to #{flash.keep.text}. This way data is not removed from the scope after first request, but is available for one more.

In managed beans, you can get flash scope by
Flash flash = FacesContext.getCurrentInstance().getExternalContext().getFlash();

Saturday, August 28, 2010

JSF 2 templating

In this post I want to share my knowledge about JSF 2 templating. Most of this post are source codes, but if you are novice and don't know how to start, and where to put the source code, here you go.

0. Download Netbeans and setup the project.

Install Netbeans and run it. I use version 6.9. In Netbeans, go to File -> New Project... and then choose Java Web and Web Application. Click Next.


In next window choose project name, optionally directory where to store it, and set the project as the main project.


In the next window leave <None> in enterprise application and choose web server. Default should be ok, the same about context path.


Check JavaServer Faces. In Libraries tab select Registered Libraries and JSF 2.0.

1. Simple template and it's client. <ui:insert> and <ui:define>

Ok, we'll create simpliest template possible. In Web Pages create new .xhtml file, let's name it headerFooter.xhtml. It's our template containing header, footer, and place for some content between them.


You can let Netbeans create it for you along with nice CSS files, you can also select one of predefined template layouts. Click File ->  New File -> JavaServer Faces -> Facelets Template. Our template code:
<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:ui="http://java.sun.com/jsf/facelets"
      xmlns:h="http://java.sun.com/jsf/html">
    <h:head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
        <title>Header-Footer Template</title>
    </h:head>
    <h:body>
        <div id="top">
            Here goes our header
        </div>
        <div id="content" class="center_content">
            <ui:insert name="content">Content</ui:insert>
        </div>
        <div id="bottom">
            And here footer
        </div>
    </h:body>
</html>
Now create template client. It is a page which uses the template. Let's call it templateClient.xhtml:
<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<ui:composition xmlns:ui="http://java.sun.com/jsf/facelets"
                template="./headerFooter.xhtml">
    
    <ui:define name="content">
        content
    </ui:define>

</ui:composition>
In template there is <ui:insert> tag. This is a named place where content from template client goes, and it's name in this case is content. In client, there is <ui:composition>. It uses template given as tags attribute, and has <ui:define> tags, with the same name as <ui:insert> in template. So what's in <ui:define> tag is inserted in place of <ui:insert> with the same name. You can run your project (in Netbeans right-click on project and select Run) and see the templated page at http://localhost:8080/JsfTemplating/faces/templateClient.xhtml Any content surrounding <ui:composition> tag is ommitted.

Template client can also be a template. Just put some <ui:insert> tag inside of <ui:define> block. E.g.
<ui:define name="content">
    <div class="info">
        Here goes some additional info, which is not in the header nor in the footer, but we need it on some pages.
    </div>
    <ui:insert name="innerContent">
</ui:define>

2. Decorate

We can also insert parts of markup in our pages. If you have piece of code which you put on some pages and it's always the same, you can separate it to a file and just insert it in the pages. <ui:decorate> tag is used for this:
<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:ui="http://java.sun.com/jsf/facelets">
    <body>
        Some page text
        <ui:decorate template="./disclaimer.xhtml"/>
    </body>
</html>
Content of disclaimer.xhtml is injected where <ui:decorate> tag is. Don't add <?xml ... ?> declaration or doctype there, or it is going to be inserted in the middle of your page, which is not desirable. You can also use standard templating in disclaimer.xhtml. You can put <ui:insert> there and <ui:define> in page which uses it.

3. Include

Another method to attach some piece of markup is <ui:include>. This one also lets us pass some parameter to the piece of code we want to include, and this parameter can be managed bean. Lets say we have bean with information about some documents:
@ManagedBean
public class Paper {

    private String author;
    private String title;

    //getters and setters omitted
}
Piece of code to display information about a book is prepared in book.xhtml file:
<div xmlns="http://www.w3.org/1999/xhtml">
    Book "#{book.title}" by #{book.author}
</div>
Now in any other JSF page we can use it:
<ui:include src="./book.xhtml">
    <ui:param name="book" value="#{tomSawyer}" />
</ui:include>
I hope this post is going to be helpful to somebody. At least to me. Happy templating with JSF!

Monday, August 9, 2010

JPA Puzzle. When your entity misses some fields.

Today I encountered quite interesting problem. It wasted few hours of my life, so maybe if you read this you can save some. Example is simplified as much as possible.
@Entity
@Table(name = "PERSONS")
@NamedNativeQueries({
    @NamedNativeQuery(
        name = "getPersonBasic",
        query = "SELECT p.name, p.surname FROM persons where p.surname = ?",
        resultClass = Person.class),
    @NamedNativeQuery(
        name = "getPersonDetails",
        query = "SELECT p.name, p.surname, p.age, p.street, p.city FROM persons where p.surname = ?",
        resultClass = Person.class)
})
public class Person {
    
    private String name;

    @Id
    private String surname;

    private int age;

    private String street;

    private String city;

}

Now, in my application I am getting Person with surname "Stawicki" without details, by "getPersonBasic" query. Then I need detailed person in the same transaction, so I execute "getPersonDetails". And... I am getting Person without age, street and city. This three fields are null. Why? Do you already know? If not, look below for answer.













The problem is in cache, and in @Id which is only on surname field. First person is retrieved without details and stored in cache. Then we try to get person with details, but JPA doesn't understand difference between our queries. It queries the database, and identifies that if it builds entity from resulting ResultSet, it is going to have the same @Id as entity which is already in cache. If @Id is the same, logically it is the same entity. So it just returns it without building whole entity from ResultSet.