I have a viewscoped bean wich receives parameters through f:viewparam and set values in the model using them. After a page postback, the parameters dissapear from the url but the model values setted by the initial params are retained somehow.
Is this a safe way of keeping parameters or should I rewrite the url on postback so it keeps the initial parameters subsequent calls?
How are the parameter retained? In the viewstate?
Here's what the f:viewParam documentation says:
[...] this tag causes a UIViewParameter to be attached as metadata for the current view. Because UIViewParameter extends UIInput all of the attributes and nested child content for any UIInput tags are valid on this tag as well.
This means that the <f:viewParam> value attribute will be updated with the request parameter, stored in the viewstate and re-set/revalidated when you submit the page again.
Arjan Tijms has the full story here: http://arjan-tijms.omnifaces.org/2011/07/stateless-vs-stateful-jsf-view.html
In short: using a #ViewScoped bean is perfectly fine, but if you use an expensive validator/converter on that value be aware that it will be called again on each postback from that page. If you want to avoid that, have a look at this article from BalusC, which explains o:viewParam, OmniFaces' stateless alternative.
Related
I'm just starting with spring so please bear with me. I've just solved a bug in my code that was coming from my assumption that once an attribute is added to any Model object, it would also be available to the templating implementation at other endpoints.
#GetMapping("/user_page")
public String getUserPage( Model model ) {
Page page = new Page();
model.addAttribute("user_page", page);
return "user_page";
In my Thymeleaf template I was able to use this attribute fine at user_page.html. Now at another endpoint and template I was also trying to use this user_page attribute. Note that it was throwing some errors:
Exception evaluating SpringEL expression:
and
Caused by: org.springframework.expression.spel.SpelEvaluationException: EL1007E: Property or field 'name' cannot be found on null
It looks like Thymeleaf couldn't find the user_page attribute.
but I also hadn't added a Model parameter to the controller that handled this other endpoint. After adding a Model to the method parameters and adding the page again model.addAttribute("user_page", page);, this time to the controller handling the different endpoint, the problem went away.
Is Spring autowiring non-singleton Model objects to these controllers? Why did I have to add the same page instance to the model twice? So are these Models tied specifically to the template (maybe even endpoint) that their respective controller returns?
Read Dispatcher Servlet Processing Sequence.
Are Spring Model objects (and their attributes) tied to their respective controller endpoints / templates?
There is no such a thing, as "Model's respective controller"; rather, a fresh instance of the Model's implementation gets instantiated each time, any handler method gets invoked.
When an HTTP request hits dispatcher servlet, and the latter passes the servlet request-response objects into the corresponding handler method, Spring MVC's infrastructure looks up the signature of corresponding handler method and passes a fresh instance of the Model (along with many others), if it is expected.
You can also use modelAttribute element in your template's form, and this way, you will directly bind the data to the handler method's Model parameter, having the argument being pre-filled with the form data. In this case, you can also enable Bean Validation.
Normally, a servlet has doGet() and doPost() methods. They are utilized to capture the incoming request parameters, which can then be used in any part of the application, if the developer wishes so.
Now, If instead of using a servlet, a developer wishes to use a jsf managed bean, is there a way to get the request parameters in the bean itself ? If so , how can it be done ?
I have seen this POST which shows a way of getting stuff from request in JSF. Can this be used to get a request parameter in managed bean like this :
HttpServletRequest origRequest = (HttpServletRequest)FacesContext.getCurrentInstance().getExternalContext().getRequest();
String myReqQuery1 = origRequest.getParameter("ReqQuery1");
In this case, will the application follow a jsf life cycle or a servlet life cycle or both ?
JSF does not really work like that. The form fields in the view (.jsf or whatever) are mirrored by fields and properties in the bean. They are automatically populated by JSF when the servlet is invoked further up the stack.
This makes the need to read HTTP parameters redundant except when the browser lands on a JSF page from a non-JSF based form. For that something like Spring-MVC can accept the URI being targetted and make a connection to the ManagedBean instance before redirecting the browser to a JSF powered URL.
I was reading an article titled: "JSF 2 GETs Bookmarkable URLs".
The article has the following paragraph:
Introducing view parameters
The API documentation describes a view parameter, represented by the javax.faces.component.UIViewParameter component class, as a declarative binding between a request parameter and a model property. The binding to the model property is expressed using an EL value expression (e.g., #{blog.entryId}). If the expression is omitted, the request parameter is bound instead to a request-scoped variable with the same name.
Could someone kindly provide an example of a request scoped variable.
A "request scoped variable" is an variable which is stored as an attribute of the HttpServletRequest.
request.setAttribute("foo", foo);
This attribute is available in EL the usual way by #{foo}. The HttpServletRequest itself has a lifetime of exactly one HTTP request-response cycle. Once the HTTP response associated with the HTTP request has arrived fully at the client (the webbrowser), then the HttpServletRequest instance, including all of its attributes, is garbaged. JSF request scoped managed beans are by the way also stored as an attribute of the HttpServletRequest.
As JSF runs "on top" of the basic HTTP Servlet API, this is all easier to understand if you also understand how HTTP and the Servlet API work. This answer might give some enlightenment: How do servlets work? Instantiation, sessions, shared variables and multithreading.
Your subsequent question shall probably be "How is this related to the quoted paragraph then?" Well, it is basically telling that, when you omit the value attribute of the <f:viewParam>, that it instead is been put as a variable in the request scope.
So, if you use
<f:viewParam name="entryId" />
instead of
<f:viewParam name="entryId" value="#{blog.entryId}" />
then it becomes available as #{entryId} in the request scope.
<p>The entry ID view parameter is: #{entryId}</p>
This is however not the way view parameters are usually been used. You'd alternatively also just have used the #{param} map instead, hereby making the whole <f:viewParam> superfluous.
<p>The entry ID view parameter is: #{param.entryId}</p>
See also:
ViewParam vs #ManagedProperty(value = "#{param.id}")
A request scoped variable is instancinated for a each single request. So a request scoped variable instance does not exist in the context of another request.
A request scoped variable is, as the name implies, only valid in the current http request. A good use for request variables is when forwarding a request from a servlet to jsp. E.g set the variable in servlet, later read the same variable in jsp with ${myvar}
example(servlet)
request.setAttribute ("greeting", "world");
getServletConfig().getServletContext().getRequestDispatcher("/jsp/page.jsp").forward(request, response);
example(jsp)
Hello ${greeting}
id is mapped with entryId in Managed-bean config or u can use annotations.
<managed-bean>
<managed-bean-name>blog</managed-bean-name>
<managed-bean-class>com.acme.Blog</managed-bean-class>
<managed-property>
<property-name>entryId</property-name>
<value>#{param['id']}</value>
</managed-property>
</managed-bean>
#RequestScope: (this is the default scope of a managed bean). This puts the bean in request scope. It makes a new instance for every HTTP request. Commonly, the bean is instantiated twice, once when form is displayed and once when it is submitted.
I have a JSF page where users can enter their car into my database. The form has three input fields:
Manufacturer
Model
Registration
The Manufacturer and Model field are both autocompletion fields. In order to complete the Model field, I need to know what value the user selected in the Manufacturer field prior to submitting the form. To that end, I set up an AJAX call to inform the managed bean of the selected value:
<p:autoComplete id="manufacturer"
minQueryLength="3"
completeMethod="#{carController.complete}"
forceSelection="true">
<p:ajax event="itemSelect"
listener="#{carController.manufacturerSelected}" />
</p:autoComplete>
And in the managed bean:
public void manufacturerSelected(SelectEvent se) {
manufacturer = se.getObject().toString();
}
The autocomplete field and handler method for the model look about the same, with slighly different values.
To retain the manufacturer value across the multiple XHR requests, I have set the bean to ConversationScoped and begin the conversation in a #PostConstruct annotated method:
#Named
#ConversationScoped
public class CarController implements Serializable {
#Inject
private Conversation conversation;
#PostConstruct
private void init() {
conversation.begin();
}
What I would expect is the bean getting only instantiated once for the page because the conversation has not been ended yet, and retaining the value in the manufacturer field. This, however, does not hold true, and the bean is instantiated again for each XHR request, causing the manufacturer field to be null as well. Setting a breakpoint in the PostConstruct method revealed that it is in fact getting called and so is the manufacturerSelected method.
I suspect this has something to do with the fact that I am not manually propagating the conversation ID but the documentation says that this ID should automatically be propagated with any faces request. Is this in fact true, and, does that mean that XHR requests are not necessarily faces requests?
Edit: Setting breakpoints at various locations in the bean has revealed that each XHR request has a new bean (conversation.getId() keeps changing) so I am obviously not propagating the ID right. How would one propagate the ID with p:ajax and where can I get it with EL?
Since you're not really using a conversation (at least not in the example you give), why not use the view scope? This will do exactly what you want, without the overhead of having to propogate a conversation id.
Do note that for #ViewScoped to work, you have to change the bean to a JSF managed bean (remove #Named). This is due to a design bug/spec oversight in Java EE 6. If you want to keep using CDI, then there's a Java EE 6 extension from Seam 3 available that fixes this bug.
Yup. This is an issue with JSF 2 and Primefaces together not propagating the conversation id. You can try the below workaround. (This is for other who will end up here due to the same issue).
<p:autoComplete id="manufacturer"
minQueryLength="3"
completeMethod="#{carController.complete}"
forceSelection="true" onchange="updateManufacturer([{name:'cid',value:'#{javax.enterprise.context.conversation.id}'}])">
</p:autoComplete>
<p:remoteCommand name="updateManufacturer" action="#{carController.manufacturerSelected}"
process="manufacturer" />
I am using Stripes but i'm not sure if this problem is because of that. I have an actionBean with a setter method setSearchView. In this setter, I set a cookie. The problem I'm seeing is that if i call that method from my jsp, the cookie does not get set (i have debugged the code and it does go through the code). If i call the same setSearchView from an action handler, the cookie is set.
Is there something I'm missing? Is this a Stripes thing or a jsp/javabean thing?
I think you are misunderstanding the programming model, I'm guessing you are coming from a CGI/Php background.
Setters/getters on Stripes action beans are used to allow the ActionBean to receive the request parameters (URL parameters in the case of GET requests, form parameters in the case of POST requests) from the browser.
You wouldn't set them manually from JSPs because you wouldn't be putting controller logic in the JSPs but in the ActionBean.
The JSP will only be used to display ('View') any data provided by the controller from the model/view-model and to display input elements to allow the user to provide input. (See MVC on Wikipedia)