2

This is a unique and curious case to me of having problems in implementing a download button using jsf 2.

So I have defined a button like this:

<h:form id="downloadForm">
    <h:commandButton value="Download" action="#{viewStatus.download()}" />
</h:form>

In my backing bean, the function looks like this:

    public void download()
    {
        String filePath = "opt/myapplication/reports/myfile.csv";
        String fileName = filePath.substring(filePath.lastIndexOf("/") + 1);

        try
        {
            File file = new File(filePath);

            FacesContext fc = FacesContext.getCurrentInstance();
            ExternalContext ec = fc.getExternalContext();
            ec.responseReset();
            ec.setResponseContentType("application/x-download");
            Long fileLength = file.length();
            ec.setResponseContentLength(fileLength.intValue());
            ec.setResponseHeader("Content-Disposition", "attachment; filename=\"" + fileName + "\"");

            OutputStream output = ec.getResponseOutputStream();
            PrintWriter printWriter = new PrintWriter(output, true);
            Scanner input = new Scanner(file);

            while(input.hasNextLine())
            {
                String line = input.nextLine();
                printWriter.write(line);
            }

            input.close();
            output.close();
            printWriter.close();

            fc.responseComplete();
        }
        catch(Exception exception)
        {
            exception.printStackTrace();
        }
    }

As you can see, I have NOT used ajax in the button and I am using the function responseComplete() to end the response.

In my page, when I click the download button, no errors are thrown, but the cursor keeps on revolving indicating that some process is going on in the background. Its like an infinite loop is going on.

After banging my head for a thousand times, when I ran the same command in a fresh project, everything works. So I know that the code is correct.

Now let me show you my JSF lifecycle log:

AFTER PHASE: RESTORE_VIEW 1
BEFORE PHASE: APPLY_REQUEST_VALUES 2
AFTER PHASE: APPLY_REQUEST_VALUES 2
BEFORE PHASE: PROCESS_VALIDATIONS 3
AFTER PHASE: PROCESS_VALIDATIONS 3
BEFORE PHASE: UPDATE_MODEL_VALUES 4
AFTER PHASE: UPDATE_MODEL_VALUES 4
BEFORE PHASE: INVOKE_APPLICATION 5
AFTER PHASE: INVOKE_APPLICATION 5

As you can see, the sixth phase - "BEFORE PHASE: RENDER_RESPONSE 6" and "AFTER PHASE: RENDER_RESPONSE 6" does not come up ever. And hence I see the cursor revolving thing, because my browser is trying to render the view, but something is blocking it, and hence the infinite loop.

So I gues my question is that does anyone know of a reason why the 6th step is not rendering and based on the given environment, can you guess what might be wrong here ?

I have seen and tried all the results that came in google relating to this matter, but nothing worked. I am not sure what is it that I am doing wrong. Also if there are any other methods to download a file, other than JSF, I will be happy to try them too.

Thanks in advance. :)

My Environment is:

  1. JSF 2.2
  2. Icefaces Ice and Ace
  3. Spring
  4. Hibernate 3
  5. Java Run Environment 1.5
BalusC
  • 1,082,665
  • 372
  • 3,610
  • 3,555
Rash
  • 7,677
  • 1
  • 53
  • 74
  • Oh yeah..i have seen this. The prblem is that I really really cannot use omniFaces. I am already using icefaces and have a restriction on me to not inlclude the application size. So I cannot include omniFaces jars and thus cannot use their functionality. – Rash Jul 15 '14 at 19:59
  • Is your file static and accesible by every user of the application? – Aritz Jul 15 '14 at 19:59
  • Yes, the file should be accessible by every user. But if you are going to suggest me to move the file location to a public directory in web-inf, I cannot do so. The file has to stay in the given folder. And by all users, I mean all users who are a part of my website, not all public users. – Rash Jul 15 '14 at 20:01
  • Not sure if this will help but try closing the resources in a `finally` block instead of inside `try`. – Omoro Jul 16 '14 at 14:41
  • @Omoro Hi. It didn't work as it shouldn't have because the problem lies not in code, but the rendering, I belive. But I agree, its always a good habit to close the resources in finally block. Thanks. – Rash Jul 16 '14 at 14:48
  • @BalusC I believe you are right. When I pressed F12, ot opened firebug and in the sending request I found this line: Faces-Request partial/ajax But how do I then send a NON AJAX request here ? Plus also the same code worked in a fresh project, how is that ? – Rash Jul 16 '14 at 19:28
  • @BalusC Also if its not too much trouble, can you please post the link of the duplicate question. I would like to see the solution there too. Thanks. – Rash Jul 16 '14 at 19:30
  • Wooooooo....you are the boss @BalusC ...it worked. And to tell you the truth, I knew I will get the correct answer from you. In all the JSF questions, I have always seen that your method worked. Thanks for sharing the answer. I am sorry that I could not find the duplicate question. Can you please also post your answer here so that I can give it a big thumbs up. – Rash Jul 16 '14 at 19:36

0 Answers0