1

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">
<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.

chardex
  • 323
  • 1
  • 5
  • 17
  • The problem is sound, but the functional requirement not. What do you want? The parameter value being included in the result URL? Or the parameter value being available inside the action method? Or both? – BalusC Sep 23 '10 at 13:46
  • Second. Inside action method. My use case is simple: one form with two modes: 1) If ID parameter doesnt specified -- it is creating new entity; 2) If ID parameter specified -- it is editing new entity. I'm new in JSF. Maybe I don't understand something? – chardex Sep 23 '10 at 13:51

1 Answers1

2

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
  • 1,082,665
  • 372
  • 3,610
  • 3,555
  • And what url will be after submit? – chardex Sep 23 '10 at 14:39
  • 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 Sep 23 '10 at 15:10
  • 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 Sep 23 '10 at 15:33
  • Use a method which you annotate with `@Postconstruct`. It will be executed after bean's construction and all dependency (managed property) injection. – BalusC Sep 23 '10 at 15:42
  • 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 Sep 23 '10 at 16:18
  • 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 Sep 23 '10 at 16:28
  • And maven dependencies: jsf-facelets 1.1.9, myfaces-api&myfaces-impl 1.1.5, tomahawk 1.1.9, jstl 1.2, jsr250-api 1.0 – chardex Sep 23 '10 at 16:40
  • It is my first web project using Java :) Sorry for such questions! – chardex Sep 23 '10 at 16:42
  • I don't understand what version I'm using. – chardex Sep 23 '10 at 16:56
  • 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 Sep 23 '10 at 17:32
  • Thanks. I'm only studing JSF, so I copied and pastied maven dependencies from someone blog. – chardex Sep 23 '10 at 17:52
  • 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 `` you can also use ``. It will render a `
    `.
    – BalusC Sep 23 '10 at 18:14
  • 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 Sep 24 '10 at 10:52
  • 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 Sep 24 '10 at 11:24
  • 1) template is in request scope and JSF 2.0 is used. @PostScript works, but after it setId is called from (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 as error (Couldn't convert #{template.hasErrors} to target class Boolean) – chardex Sep 24 '10 at 11:57
  • 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 Sep 24 '10 at 11:59