Issues with uploads in JSF

Almost every 3rd party JSF component library comes with a file-upload-component. So do the Apache MyFaces component libraries Tobago, Tomahawk or Trinidad. This blog speaks about Trinidad, but it is true for other JSF component libraries as well.

Imagine you have a form, to update some data, like the first name or a birth date value. You would have a save-button, that doesn’t cause navigation to stay on the page. And on every submit the the same data goes back to the server, unless you change it, before pressing the save-button:

<tr:form>
  <tr:inputText label="Text" value="#{bean.data}" />
  <tr:commandButton text="save data" />
</tr:form>

Now imagine you have to add a new field, one to take the picture of the person you are editing. Some HR-Systems have that requirement. A screenshot could look like this:

step1.png

When you click save, to upload the file, the page rerenders like this:

wrong_step2.png

Now, when you try to click again the save… you’ll notice a validation error, that you have to submit a file. Hey, didn’t I a second before ??

wrong_step2_validation.png

Why is that happening ? Why is the HTML input widget rendering empty, and the regular text-input not ?
One issue is that you can’t render out something like <input type="file" value="mypic.png" />.
And even if you could. What would it upload, in case you don’t have the mypic.png on your box and, hey… to what directory??

So it makes sense that we see this, at least from a security standpoint.

Perhaps a UI-design like this is a bad thing. So, what can you do ? And how to ensure, the editor is able to change the picture again?

Here is a way, how your form could look:

<tr:inputFile label="Photo" required="true"
    value="#{worker.photo}"
    rendered="#{worker.photo == null}"  />

<tr:inputText label="Photo" readOnly="true"
    required="true" value="#{worker.photo.filename}"
    rendered="#{worker.photo != null}"  />
<tr:commandButton returnListener="#{worker.handleReturn}"
    partialSubmit="true" immediate="true"
    text="Update" rendered="#{worker.photo != null}"
    action="dialog:update" useWindow="true"
    windowWidth="374" windowHeight="266"  />

As you notice, when there is no photo, an inputFile component will be used (see the rendered attribute). In case there is a photo present, for the worker, we will see a readonly inputText and an update-button:

step2.png

When you now press save, no validation error happens. That helps.The update-button is a bit special. It causes the Trinidad-Dialog-Framework to open a new page (in this case in a new browser-window). The new window shows an inputFile component and a button, to change the picture. Note, here is input field is empty as well, but it doesn’t hurt in this case! So, select a new file…

step3.png

Once the user is clicking the “save” button in this window, the window closes and via PPR the forum will be updated, to reflect the change:

step4.png

And again… the SAVE button does cause no validation error. So this could be a solution to the problem. To get this working a little bit Java is needed.
The action method behind the “Save the new photo” button looks like:

public String updater()
{
  RequestContext.getCurrentInstance().returnFromDialog(null, null);
  return null;
}

And the returnListener from the update-button looks like this, to trigger PPR, to have the new filename visible, once the little window is gone:

public void handleReturn(ReturnEvent event)
{
  UIXForm form = (UIXForm) event.getComponent().findComponent("theIdOfMyForm");

  RequestContext.getCurrentInstance().addPartialTarget(form);

}

That’s all. Perhaps that helps a bit. A nice overhaul of this exercise would be to create a declarative component, using Facelets!

Howdy!

Posted in apache, jsf, Uncategorized

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: