my dog learned polymorphism*
The moose likes JSF and the fly likes Doubt using JS to call a h:commandButton Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login
JavaRanch » Java Forums » Java » JSF
Bookmark "Doubt using JS to call a h:commandButton" Watch "Doubt using JS to call a h:commandButton" New topic
Author

Doubt using JS to call a h:commandButton

Rafael Campos Cruz
Ranch Hand

Joined: Apr 16, 2013
Posts: 39
Hi everyone!

I'm trying to "click" a hidden h:commandButton on my xhtml page, however it isn't working: the method on the commandButton is never called.

This is my code so far:

The JavaScriot




The button that should be called



The outputLink that calls the JS function





Why the my MB method isn't being called? Is the js wrong?

And I think I have to add that my page is using a template and, on the template, there's already a <script..> call
Bear Bibeault
Author and ninkuma
Marshal

Joined: Jan 10, 2002
Posts: 61094
    
  66

Please be sure to post JSF questions in the JSF forum. I have moved this post there for you.


[Asking smart questions] [Bear's FrontMan] [About Bear] [Books by Bear]
Rafael Campos Cruz
Ranch Hand

Joined: Apr 16, 2013
Posts: 39
Oh, sorry...

thought it was more JS related...
Rafael Campos Cruz
Ranch Hand

Joined: Apr 16, 2013
Posts: 39
Hum, I figured out that "onkeypress" wasn't calling the js method, so I changed it for "onclick" and it worked!

Well, sort of.

It still ins't calling the commandButton, is the overload of the ".click()" wrong? How?

And another thing, I put an alert after the "document.getElemenstByTagName("formulario:prepFile").click();" and it isn't being called, BUT one before is...


so I believe the execution is being interrupted on this line, why?
Tim Holloway
Saloon Keeper

Joined: Jun 25, 2001
Posts: 16019
    
  20

Depending on what version of what browser you are using, the JavaScript construct "document.getElementsByTagName("formulario:prepFile")" may not work properly. First, because the internal location mechanisms may not like IDs in the form of "x:y:z" and have to be escaped. Secondly, because getElementsByTagName returns a list (array) of elements, not a single element, even though there might be only 1 (or zero) elements in the collection. And, come to think of it, I believe the JavaScript function you need is named "getElementById". IDs must be unique, Names do not have to be unique, and a Name is not the same thing as an ID.

Aside from that, however, I still think you are over-complicating things and probably should get rid of ALL the JavaScript and use an "h:commandLink" for your image.


Customer surveys are for companies who didn't pay proper attention to begin with.
Rafael Campos Cruz
Ranch Hand

Joined: Apr 16, 2013
Posts: 39
After some tinkering around and learning some bits I managed to get my JSF working... however I'm having the following problem:

The click event happens but the action isn't called on the button.

I have a System.out.... in the MB method wich should be called by the button so I'm 100% sure that it isn't being called, however,
I added an alert to "onclick" in the commandButton:



the alert do shows up, but to no good...

my new JS is



and the outputLink that calls everything:



is there a way to make the action calling be handled before the outputLink is resumed?
Tim Holloway
Saloon Keeper

Joined: Jun 25, 2001
Posts: 16019
    
  20

I'm sorry. I can only repeat that I think you are over-complicating your solution and that all you probably need is a commandLink and no JavaScript.

I've been working with JSF mostly full-time since 2006 and I almost NEVER interact directly with the Component Tree. JSF is designed to to most of its work using POJOs with minimal use of JSF-specific code.
Rafael Campos Cruz
Ranch Hand

Joined: Apr 16, 2013
Posts: 39
But you stated here that I could only call a File Download Servlet by using a outputLink... it don't work using a commandLink...
Tim Holloway
Saloon Keeper

Joined: Jun 25, 2001
Posts: 16019
    
  20

Rafael Campos Cruz wrote:But you stated here that I could only call a File Download Servlet by using a outputLink... it don't work using a commandLink...


No. You cannot literally "call a servlet" from an outputLink. Servlets are not "callable", in any case, technically speaking.

An outputLink will generate a URL for the client to use (actually, it generates an <a href= > tag). When the client user clicks on the generated hyperlink, that will cause the client application (browser) to submit a an HTTP request whose URL is the URL that the outputLink tag generated, which should be the URL of the servlet that generates the actual output to be downloaded.
Rafael Campos Cruz
Ranch Hand

Joined: Apr 16, 2013
Posts: 39
Is there any way to call a MB method and generate the URL without making something horrible like changing the button after the click?
Tim Holloway
Saloon Keeper

Joined: Jun 25, 2001
Posts: 16019
    
  20

I have no idea what you are hoping to do.

Could you explain this from the user view instead of a "I have a technical problem" view? A lot of times, when you assume that you have to use a specific technical solution it can blind you to simpler, cleaner ways of solving the problem.

In other words, what is the page supposed to look like, and what is the user expected to do to the page and what should the user see in response to that action?
Rafael Campos Cruz
Ranch Hand

Joined: Apr 16, 2013
Posts: 39
I want a button that the user can click and it will download the file with all the data inside... just that
Tim Holloway
Saloon Keeper

Joined: Jun 25, 2001
Posts: 16019
    
  20

Rafael Campos Cruz wrote:I want a button that the user can click and it will download the file with all the data inside... just that


That's simple enough. An outputLink will generate that.

If you want the link to look like an actual button, you can do 1 of 2 things:

1. Use raw HTML instead of JSF and define a raw HTML <FORM> (not an h:form, and make its ACTION= value be the URL. Put a raw HTML BUTTON object in the form so that the user can click on it to submit the form.

2. Use h:outputLink to create a hyperlink and use CSS to make the link look like a button. This is actually a very common thing.
Rafael Campos Cruz
Ranch Hand

Joined: Apr 16, 2013
Posts: 39
But there's a problem... I need to first get the data inside the file prior to downloading it...

in the page where these buttons will be the "data" which will go to the file is chosen (the are objects of a List and the user removes the ones wich he doesn't want) and the only way I can see of putting it inside the said file is through a MB method...
Tim Holloway
Saloon Keeper

Joined: Jun 25, 2001
Posts: 16019
    
  20

OK. The traditional method would be to present the options on a form, have the user submit the form, then present the page that contains the download link/button. You transfer the options by making the JSF form backing bean be session-scoped so that the download servlet can then access the session object in the traditional way.

There are variations on this scheme that can be done if you don't want the actual download button to be on a new page. For example, you can disable the link on load and use AJAX to update the backing bean and enable the link when the options have been selected. Or, you can use raw HTML form controls and make their onblur actions modify the URL parameters and pass the options in that way instead of using a backing bean. I don't recommend that, for a number of reasons, but it can be done.
Rafael Campos Cruz
Ranch Hand

Joined: Apr 16, 2013
Posts: 39
My fear is that, as the data is saved in a real file and many users will extract data the same way, the file be overwritten before the user have a change to download it.
Tim Holloway
Saloon Keeper

Joined: Jun 25, 2001
Posts: 16019
    
  20

Use the java.io.File's tempFile() method to create a temporary filename. Write the data to be downloaded into that file. Save the file's pathname (or the equivalent File object) as one of your session objects so that the download servlet can find it, open it, and copy its contents to the requesting client. Once you have written the file's contents out to the HttpServletResponse stream, you can delete the temporary file and discard the session object. Or keep it if you think that someone might download it more than once, but make sure you have a housekeeping service that periodically cleans out the old unwanted files.
Rafael Campos Cruz
Ranch Hand

Joined: Apr 16, 2013
Posts: 39
Hum... I'm having one last problem but, all on all, it worked just fine having the "setting up the file" and the "downloading the file" on separate pages.

My Glassfish Application Server runs inside a Linux machine and when I download the file accessing the application in the browser INSIDE the server, it works perfectly.

But, when I access it from the outside (when I access the application through a browser using its network address on a machine wich is not the server) the first time it will work correctly, but after that it will always copy the first file wich was extracted.

Not just that, the application won't delete the temporary file which was created and this allowed me to see something: the file created is correct, but not the one sent to the user.

By checking the logs I discovered that, when being called inside the server the Download Servet method doGet is called for each and every request that is deployed from the browser.

The same doesn't happen by making calls outside the server, the servlet is called just 1 time and never more, like if it's now waiting for requests with the doGet already running...

How can I force it to call doGet everytime? Is this a normal behavior?


Tim Holloway
Saloon Keeper

Joined: Jun 25, 2001
Posts: 16019
    
  20

You should not be calling a servlet's goGet() method yourself. doGet() is called from the HttpServlet service() method, which in turn is invoked by the web application server itself (Glassfish) in response to an HTTP GET URL request received from a client (browser). In your case, because the user clicked on the form submit button to initiate downloading.

Servlets are not programs. Their closest Windows equivalents would be DLLs. The methods inside a servlet are intended to be invoked by the appserver, not by application code.
Rafael Campos Cruz
Ranch Hand

Joined: Apr 16, 2013
Posts: 39
I expressed myself badly, sorry. It's just as you said: the button calls the address which I setted up on web.xml (in my case "baixar").

Either way, I may click the button in several instances, but only one of then will summon the servlet...
Tim Holloway
Saloon Keeper

Joined: Jun 25, 2001
Posts: 16019
    
  20

That's OK. I think that I misread things anyway.

It sounds like the problem is that your browser is caching the file on the first request. You might want to make the servlet return no-cache headers to prevent that.
Rafael Campos Cruz
Ranch Hand

Joined: Apr 16, 2013
Posts: 39
How do I do that? What should I research for?
Rafael Campos Cruz
Ranch Hand

Joined: Apr 16, 2013
Posts: 39
Hum...

after some research I found some aswers, I tried the following:



for no effect...

I'm trying to search an alternative but a FAQ that I found said that this should sort it all out, why it doesn't?
Rafael Campos Cruz
Ranch Hand

Joined: Apr 16, 2013
Posts: 39
Lol, I put the code at the beggining of the doGet and it worked! I still would like to understand why it work only this way, but yeay!
Tim Holloway
Saloon Keeper

Joined: Jun 25, 2001
Posts: 16019
    
  20

Rafael Campos Cruz wrote:Lol, I put the code at the beggining of the doGet and it worked! I still would like to understand why it work only this way, but yeay!


Probably because ALL headers must be written to the Response stream before ANY content can be written. That includes cookies and so forth. If you write even a single content byte, then at best, any headers you add will be included as part of the content instead of a header, and at worst, you'll probably trigger an IllegalStateException.
 
I agree. Here's the link: http://aspose.com/file-tools
 
subject: Doubt using JS to call a h:commandButton