3

I have a form in JSF 2.2:

<h:form enctype="multipart/form-data">
    <h:outputLabel>title *</h:outputLabel>
    <h:inputText value="#{bean.title}" required="" />

    <h:outputLabel>Image *</h:outputLabel>
    <h:inputFile value="#{bean.picutreFile}" a:accept="image/*">
        <f:ajax listener="#{bean.uploadPicture}" />
    </h:inputFile>

    <h:commandLink action="#{bean.save}">
        Save
    </h:commandLink>
</h:form>

The functions:

public String save() {
    return "/index?faces-redirect=true";
}

public void uploadPicture() {
    // Do nothing
}

But after I choose an image and get the call of uploadPicture function, the save function can't redirect the page. It calls to save but the redirect is not working, and just refresh the current page.

If I skip the file upload, it redirects normally. How can I make it to work?

EDIT
I have noticed that if I remove the ajax <f:ajax listener="#{bean.uploadPicture}" /> it works as expected. But I must to have that ajax because I want to display the image after upload.

EDIT 2
I can see that after the ajax called, the JSF creates a weird iframe at the bottom of the page with partial-response tag in it's body, and when I press 'Save` that iframe is redirects to the destination. Why is that??

nrofis
  • 8,975
  • 14
  • 58
  • 113
  • Which JSF impl/version? Early 2.2 versions have childhood bugs with h:inputFile. See also http://stackoverflow.com/tags/jsf/info for hints. – BalusC Apr 14 '16 at 14:09
  • @BalusC When I open the JSF's JAR inside the GlassFish libraries in NetBeans I can see `Bundle-Name: Mojarra JSF Implementation 2.2.12 (20150720-0848) https:/ /svn.java.net/svn/mojarra~svn/tags/2.2.12@14885`, I am also using GlassFish 4.1.1 – nrofis Apr 14 '16 at 14:15

2 Answers2

2

I reproduced it. I do agree that the behavior is confusing and unintuitive, but I wouldn't say this is a bug in the JSF implementation, because you're essentially mixing ajax with regular requests which is wrong in first place. See also this related question httpError: The Http Transport returned a 0 status code.

The correct approach is either to make the command link an ajax link as well,

<h:commandLink action="#{bean.save}">
    Save
    <f:ajax execute="@form" />
</h:commandLink>

or to remove <f:ajax> from the <h:inputFile> (and perform upload processing in save()).

<h:inputFile value="#{bean.picutreFile}" a:accept="image/*" />

That iframe you're seeing is by the way the age-old trick to simulate asynchronous behavior during file uploads, invented long before XHR2 / FormData API was standardized. This approach was during JSF 2.2 development preferred over XHR2 due to better backwards compatibility in webbrowsers (particularly MSIE). See also a.o. How to make Asynchronous(AJAX) File Upload using iframe?

Community
  • 1
  • 1
BalusC
  • 1,082,665
  • 372
  • 3,610
  • 3,555
  • I didn't know that mixing ajax with regular is wrong, because the ajax was just for display preview of the image. But with `` its works perfectly. Thank you! – nrofis Apr 14 '16 at 14:34
-1

As I know JSF blocks your request till ajax call for security. Maybe you can put a processing bar or something like that while ajax calling. So user can not click save button until ajax call finish.

Can you wait a little bit after clicking upload button then click save button? It should work If i am right.

  • When I debug it, I press "Save" after `uploadPicture` ends. Isn't good enough? BTW, I am using 5KB photos only so I don't think it's need so much waiting time – nrofis Apr 14 '16 at 13:33