Proper way to call servlet from Facelets?

facelets, jsf, servlets

Solution

Just use a plain HTML `<form>` instead of a JSF `<h:form>`. The JSF `<h:form>` sends by default a POST request to the URL of the current view ID and invokes by default the `FacesServlet`. It does not allow you to change the form action URL or method. A plain HTML `<form>` allows you to specify a different URL and, if necessary, also the method.

The following kickoff example sends a search request to Google:

<form action="http://google.com/search">
    <input type="text" name="q" />
    <input type="submit" />
</form>

Note that you do not need to use JSF components for the inputs/buttons as well. It is possible to use `<h:inputText>` and so on, but the values won't be set in the associated backing bean. The JSF component overhead is then unnecessary.

When you want, for example, to send a POST request to a servlet which is mapped to a URL pattern of `/foo/*` and you need to send a request parameter with the name `bar`, then you need to create the form as follows:

<form action="#{request.contextPath}/foo" method="post">
    <input type="text" name="bar" />
    <input type="submit" />
</form>

This way the servlet's `doPost()` method will be invoked:

@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    String bar = request.getParameter("bar");
    // ...
}

Problem

What is the proper way to call a servlet from a facelets file using a form with submit button? Is there a particular form required?

Original source