views:

97

answers:

1
+1  Q: 

Jsf form action

Hi! I have simple JSF form:

<html xmlns="http://www.w3.org/1999/xhtml" xmlns:ui="http://java.sun.com/jsf/facelets"
      xmlns:t="http://myfaces.apache.org/tomahawk" xmlns:h="http://java.sun.com/jsf/html" xmlns:f="http://java.sun.com/jsf/core"&gt;
<ui:composition template="layout.jsp">
    <ui:define name="title">Редактирование шаблона</ui:define>
    <ui:define name="content">
        <t:div rendered="#{template.hasErrors}">
            #{template.errorText}
        </t:div>
        <t:div rendered="#{template.hasMessage}">
            #{template.messageText}
            <p>
                <a href="/templates.jsf">Все шаблоны</a>
            </p>
        </t:div>
        <t:div rendered="#{template.canEdit}">
            <h:form>
                Name: <h:inputText value="#{template.name}"/> <br/>
                Content Type: <h:inputText value="#{template.contentType}"/> <br/>
                Content: <h:inputTextarea value="#{template.content}"/> <br/>
                Description: <h:inputTextarea value="#{template.description}"/> <br/>
                <h:commandButton value="Сохранить" action="#{template.submit}">
                </h:commandButton>
            </h:form>
        </t:div>
    </ui:define>
</ui:composition>
</html>

Everything works, but when I'm trying to use this page with query string parameters (template.jsf?Id=5) and then sumbit command button -- page is redirected to template.jsf (witout query string parameter. And it is clear -- form action attribute always ="template.jsf", even query string parameters are passed). So I can't call submit method for TemplateBean with specified query string parameter.

+2  A: 

Add a property id to the template bean:

public class Template {
    private Long id; // +getter +setter
}

Instruct JSF in the faces-config to set it with #{param.id} during bean's creation:

<managed-bean>
    <managed-bean-name>template</managed-bean-name>
    <managed-bean-class>com.example.Template</managed-bean-class>
    <managed-bean-scope>request</managed-bean-scope>
    <managed-property>
        <property-name>id</property-name>
        <value>#{param.id}</value>
    </managed-property>
</managed-bean>

Retain the property in subsequent request by passing it through as hidden input field in the same form:

<h:inputHidden value="#{template.id}" />

Then you can access it the usual way in action method:

public String submit() {
    System.out.println("id: " + this.id);
    return null;
}
BalusC
And what url will be after submit?
chardex
The form's action url. Thus, the parameter will disappear. But as per your comment this wasn't the functional requirement? It would otherwise going to be a 5 times bigger answer since that's not that obvious/easy in JSF.
BalusC
Huge thanks! If it is difficult - it is not necessary. I now understand more. In the bean object I need to load the template object from the data layer. Until then, I did it in the constructor of template bean, and then all the getters return the fields from data object, and setters - sets fields of this data object. Now, this scheme does not work, because real object identifier I get twice (two calls of setId): one from the query string, the other from the hidden field. Could you give an example of such bean? At what point does the right way to load data object from the data layer?
chardex
Use a method which you annotate with `@Postconstruct`. It will be executed after bean's construction and all dependency (managed property) injection.
BalusC
Thanks. I added method @PostConstruct public void init(){LOG.info("init")}, but is doesn't called. Only gettters calls are logged. jsr250-api is in classpath. Very strange.
chardex
So you're using legacy JSF 1.1? The `@PostConstruct` was introduced in JSF 1.2, already over 4 years old. Verify if your JSF libraries comply 1.2 and your `faces-config.xml` root declaration also.
BalusC
chardex
It is my first web project using Java :) Sorry for such questions!
chardex
I don't understand what version I'm using.
chardex
MyFaces 1.1.5, so you're using the 6 year old JSF 1.1 (ouch). Since you've declared faces-config as JSF 2.0 and web.xml as Servlet 2.5 and are already using Facelets, why don't you upgrade to JSF 2.0? It offers [major](http://stackoverflow.com/questions/3623911/what-are-the-main-disadvantages-of-java-server-faces-2-0) advantages. Replace the [MyFaces](http://myfaces.apache.org) JAR's by the 2.0 ones, or just use [Mojarra 2.0](http://javaserverfaces.dev.java.net).
BalusC
Thanks. I'm only studing JSF, so I copied and pastied maven dependencies from someone blog.
chardex
Note that Facelets is already included in JSF 2.0. Also note that Tomahawk is not officially compatible with JSF 2.0, although most components will work. Instead of `<t:div>` you can also use `<h:panelGroup layout="block">`. It will render a `<div>`.
BalusC
I have three new related problems: 1) after submit I don't receive id from hidden field in @PostConstruct method. I receive it later in setId(). So where I should load datalayer entity? 2) After migrating to JSF 2.0 I receive NullReferenceException after submitting command button, like in this post you have unswered: http://forums.sun.com/thread.jspa?threadID=5412526 But I don't have sessions or JDBC. It appears after loading from DB (and threre is no my code in stack trace). 3) If I use h:panelGroup insted of t:div I can't setup rendered attribute like before, but I need it.
chardex
1) Your bean needs to be in request scope (and you should be using at least JSF 1.2). 2) NullReferenceException doesn't exist in Java. Please ask a new question with entire trace. 3) You can just keep using `rendered` attribute in `h:panelGroup`.
BalusC
1) template is in request scope and JSF 2.0 is used. @PostScript works, but after it setId is called from <h:inputHidden value="#{template.id}" /> (as you adviced). 2) Sorry, NullReferenceException is from .NET, I mean NullPointerException. Here is new question http://stackoverflow.com/questions/3786772/jsf-2-0-nullpointerexception-exception-after-submitting-commandbutton. 3) Strange, IntelliJ IDEA 9 highlited <h:panelGroup rendered="#{template.hasErrors}"> as error (Couldn't convert #{template.hasErrors} to target class Boolean)
chardex
1) I don't understand the problem then. 2) Okay. 3) IntelliJ is apparently not as intelligent as you think. Just ignore and run it.
BalusC