How to pass parameters via URL to a bean class using JSF? - java

I have created a login page for my JSF application. I want to pass the username and password as parameters via the URL to later receive them as fields in a bean class. How can I do this?

You should pass it as POST parameter which is what JSF does by default ,
You can google for a quick example of a Login page with JSF , however if you want to read the request parameters from URL then you can do like
<a href="name.jsf?id=#{testBean.id}" />
You need something like this in your bean
#ManagedBean
#RequestScoped
public class TestBean {
#ManagedProperty(value = "#{param.id}")
private String id;
.....
}
You can also do this in your xhtml to get the same outcome, this will work with JSF 2.x as viewParam is not available in JSF 1.2
<f:metadata>
<f:viewParam name="id" value="#{testBean.id}" />
</f:metadata>
Above line will set the parameter id in bean from the request parameter id when your bean is created.

Well first of all, if you are thinking of appending the username and password as part of query string. THEN DO NOT DO IT, you are making your system vulnerable.
Regarding the answer to your question:
<h:commandLink action="#{ttt.goToViewPage()}" value="View">
<!-- To access via f:param tag, this does not maps directly to bean. Hence using context fetch the request parameter from request map. -->
<!-- <f:param name="selectedProfileToView" value="#{profile.id}" /> -->
<!-- Using this to replace the f:param tag to avoid getting the request object -->
<f:setPropertyActionListener target="#{ttt.selectedStudentProfile}" value="#{profile.id}" />
</h:commandLink>
f:param (as mentioned in comment), this will not map directly to the bean attribute, but you will have to use context to get the request object from which you can reference the value from the requestparametermap.
FacesContext context = FacesContext.getCurrentInstance();
Map<String, String> requestMap = context.getExternalContext().getRequestParameterMap();
f:setPropertyActionListener, this is the other attribute, which will map directly to the attribute of the managed bean.
<h:commandLink action="#{ttt.goToEditPage(profile.id)}" value="Edit">
If you look here I have mentioned the argument in the function. A method with similar signature should be present in the managed bean class, the value will be mapped directly to the function argument.

Related

Which properties in a JSF backing bean can be set by a user?

I have a backing bean (somebean) with three boolean properties a, b, and c, each has a getter and setter.
I have a form which looks like this:
<h:outputText rendered="#{somebean.b}">
B is true
</h:outputText>
<h:form id="blah">
<h:inputHidden value="#{somebean.a}" id="a"/>
<h:commandLink id="zzzz" value="do it" action="#{somebean.doIt}"/>
</h:form>
Which of the three properties a, b, and c can be set by the client? I tried adding b=true and c=true to the POST request, but SomeBean.setB(boolean) and SomeBean.setC(boolean) never get called. So perhaps only a can be set - the logic being that if there is a field in the JSF that sets it, the client is allowed to set it. But perhaps I'm wrong and it just has some default name that I don't know about that can be used to set it...
Should I just assume that any property on my bean can be set by the client? If not, which ones should I assume the client can set (and thus have to worry about during validation)?
Also what happens if I have my form conditionally rendered? e.g:
<h:outputText rendered="#{somebean.b}">
<h:form id="blah">
<h:inputHidden value="#{somebean.a}" id="a"/>
<h:commandLink id="zzzz" value="do it" action="#{somebean.doIt}"/>
</h:form>
</h:outputText>
In this case, can a still be set if b is false?
By "client", I mean anything sending HTTP traffic to my site. Which could be for example, malicious code.
Which properties in a JSF backing bean can be set by a user?
Those bound to an EditableValueHolder component, such as UIInput and friends (including <f:viewParam>!), with the precondition that they are rendered="true", disabled="false" and readonly="false" during apply request values phase.
Another possible way is through a #ManagedProperty("#{param.xxx}") on the property of a request scoped bean or a hardcoded ExternalContext#getRequestParameterMap() access in some bean method which is invoked during the HTTP request.
So, only when you as being the developer explicitly bind the property to an editable value holder component which is rendered, non-disabled/readonly, or when you as being the developer explicitly set a request parameter as a property. There are in the current releases of JSF implementations absolutely no security holes with reagard to the possibility of setting undeclared/unbound properties by HTTP means. It's even not possible to send an arbitrary value to a UISelectOne or UISelectMany component by spoofing the HTTP request, it would only end up in "Validation Error: Value is not valid".
As to security holes in older JSF implementations, only and only when you're navigating to a different view using includeViewParams="true" in a Mojarra version older than 2.0.7 and 2.1.5, then all EL expressions in view params such as #{bean.setArbitraryProperty('foo')} will be evaluated. See also issue 2247. I'm not aware of any security holes in MyFaces; that's not because there are none per se, but simply because I don't use/track it closely.

f:param is null in bean jsf

My problem is that the value of the parameter is null in the bean
In the xhtml I have this code:
<h:commandLink action="#{navigation.editNews}" value="#{new.title}">
<f:param name="newsId" value="#{new.id}" />
</h:commandLink>
In Navigation I redirect to news.xhtml
public String editNews(){
return "editNews";
}
This is the code in faces-config.xml
<navigation-case>
<from-action>#{navigation.editNews}</from-action>
<from-outcome>editNews</from-outcome>
<to-view-id>/news.xhtml</to-view-id>
<redirect />
</navigation-case>
I have a bean where I call method when I push a button in news.xhtml and I try to get param but it is null
FacesContext fc = FacesContext.getCurrentInstance();
Map<String,String> params = fc.getExternalContext().getRequestParameterMap();
String = params.get("newsId");
The <f:param> adds a request parameter. So this parameter has a lifetime of exactly one HTTP request. You've a <redirect/> in your navigation case which basically instructs the webbrowser to send a new request on the given location. This new request does not contain the parameter anymore.
You've basically 2 options:
Get rid of <redirect /> in the navigation case.
Make it a normal GET request instead. If you're on JSF2, use <h:link> instead.
<h:link action="news" value="#{news.title}">
<f:param name="newsId" value="#{news.id}" />
</h:link>
Or if you're still on JSF 1.x (the usage of navigation cases less or more hints this as they are superfluous in JSF 2 thanks to the new implicit navigation feature; or you must be reading outdated tutorials/books/answers targeted on JSF 1.x; also the absence of JSF 2.0 tag on your question is suspicious), then use a normal <a> link instead.
#{news.title}
See also:
Communication in JSF 2.0 - Processing GET request parameters

JSF 2.0 return null from action methods does not retain the original request parameters

I have a JSF application with a particular page to show/edit the details of a particular entity in my system (an attraction). I have a jsf page which takes the attractionId as a page parameter as follows:
<f:metadata>
<f:viewParam name="attractionId" value="#{attractionsBean.attractionId}" required="true" />
</f:metadata>
To submit the changes to the attraction I have this command button:
<p:commandButton styleClass="button"
ajax="false"
value="Update Attraction"
action="#{attractionsBean.updateAttraction()}" />
In the updateAttraction method, normally in JSF when you return null, the user is redirected to the same page showing any messages that might have been created. However, since the page requires an attractionId, it gives a validation error that the attractionId is null since it does not automatically add the original request parameter. Normally I do it as follows:
if (FacesContext.getCurrentInstance().getMessageList().size() > 0) {
return null;
}
But this does not send back the original parameters to display the specified attraction.
Can anyone suggest a clean solution for this please?
Thanks!!
You can add the includeViewParams=true parameter to an outcome to let jsf impl append all declared view parameters, but I think this can only work if you also include the view id. You could try something like this:
return FacesContext.getCurrentInstance().getViewRoot().getViewId() + "?includeViewParams=true";
Or you could define a constant including the view id in your managed bean:
private static final String SUCCESS = "attraction?includeViewParams=true";
...
if (FacesContext.getCurrentInstance().getMessageList().size() > 0) {
return SUCCESS;
}
Some more examples for this param can be found at this blog post about POST-REDIRECT-GET and JSF 2.0.

strange jsf issue

I have a facelet component for displaying rss content:
rssFeedReader.xhtml
<h:outputText
binding="#{rssReaderBean.text}"
value="#{url}">
<f:attribute
name="url"
value="#{url}" />
</h:outputText>
<ui:repeat
value="#{rssReaderBean.rss}"
var="rss">
<ice:panelGroup>
<ice:outputLabel
value="#{rss['publishDate']} - "
rendered="#{not empty rss['publishDate']}">
</ice:outputLabel>
<a
href="#{rss['link']}"
target="_blank">#{rss['title']}</a>
</ice:panelGroup>
<ice:panelGroup>
<ice:outputLabel>#{rss['description']}</ice:outputLabel>
</ice:panelGroup>
<hr />
</ui:repeat>
and I include it where I need it like:
<myLib:rssFeedReader url="http://rss.news.yahoo.com/rss/topstories"></myLib:rssFeedReader >
If I include it with different urls, multiple times on my page, I do not understand why it displays multiple times the same FIRST url rss feed insted of taking each url separately.
To be able to read the specified url in my bean I bind it to the h:outputText from my facelet. Code from RssReaderBean bean:
private HtmlOutputText text;
public HtmlOutputText getText() {
return text;
}
public void setText(final HtmlOutputText text) {
this.text = text;
}
and the method which takes the url and returns the list:
public List<Rss> getRss() {
try {
final URL u = new URL((String) text.getAttributes().get("url"));
///read the rss feed and prepare the result, this code works good so its not required here
}
Can you see the problem...?
Thanks.
UPDATE: The bean has Request scope specified in faces-config.xml. If I print out the value of the text url it shows the LATEST url but all the content is taken from FIRST...
so basically for:
<gra:rssFeedReader url="http://blog.test.com/feed/rss/"></gra:rssFeedReader>
<gra:rssFeedReader url="http://rss.news.yahoo.com/rss/topstories"></gra:rssFeedReader>
it prints out the content of blog.test.com but text value when the page is rendered will show empty for first and yahoo url from second one...
The problem is caused because you're binding the <h:outputText> of the tag file to a single bean property. So, everytime you add another <myLib:rssFeedReader> tag, it will override the binding with the last added tag in the view. Finally, when #{rssReaderBean.rss} is been evaluated during rendering the view, it has only the last one at it hands.
There are several ways to solve this. The cleanest way is to create a fullworthy custom UIComponent wherein you specify the URL as an attribtue. The attribute is supposed to be specific to the component, not to a single bean property. An alternative is to use a Map<String, HtmlOutputText> property instead, this is however going to be clumsy.
Or if you're running a Servlet 3.0 / EL 2.2 capable container or replace the standard EL implementation by one which accepts method arguments, such as JBoss EL, then you could pass the URL as argument instead. E.g. #{rssReaderBean.rss(url)}. For installation/configuration detail, see this answer.

JSF property transfer from backing bean A to backing bean B

I'm getting deeper into JSF 2.0 at the moment and lacking a bit of understanding about the "transport" of managed bean properties from one view to the other. I searched a bit but haven't found a really good example, so if anyone could point me to a tutorial or explain the things a little bit I'd really grateful.
So here is my scenario:
I'm developing a small playground calendar application. The first view select.xhtml contains the calendar selector, where the user can pick a specific date:
<html>
...
<h:form>
<!-- Calendar selector from primefaces -->
<p:calendar value="#{calendarSelect.date}" mode="inline" navigator="true" />
<p:commandButton value="Show entries for date" action="day" />
...
My corresponding backing bean looks like this:
#ManagedBean(name="calendarSelect")
#RequestScoped
public class CalendarSelectComponent {
private Date date = null;
... // Getters and setters
Now when I submit the form from select.xhtml I'm forwarded to day.xhtml
<html>
...
<h:form>
The current day ist:
<h:outputText value="#{calendarEdit.date}">
<f:convertDateTime pattern="dd.MM.yyyy" />
</h:outputText>
The backing bean now looks like this:
#ManagedBean(name="calendarEdit")
#ViewScoped
public class CalendarEditComponent implements Serializable {
private Date date = null;
private CalendarEntryBean currentEntry = null;
private List<CalendarEntryBean> allEntries = null;
....
I am now trying to solve the problem: How do I transfer the date parameter from the selector to the editor?
I've tried a number of options, one was this:
<p:commandButton value="Show entries for date" action="day" />
<f:setPropertyActionListener target="#{calendarEdit.date}" value="#{calendarSelect.date}" />
</p:commandButton>
A debugger shows, that indeed, the date property of the calendarEdit is populated with the value from calendarSelect, but since day.xhtml is a new view, a new CalendarEditComponent backing bean is being created and not the one I've populated with the date from the selector in the select view.
I've read that one solution would be to create a SessionScoped backing bean that does retain all it's values. But this is not the way I think it's supposed to work, because I don't really need the information in the session, I simply want it to "travel" from A to B. Another downside with the session based approach is that I can only use one selector and one editor per session - which I think isn't acceptible if you think of multi window browsing and so on.
I really don't think I'm the first one encountering such a scenario and I'm sure that JSF provides an elegant solution for this but I haven't been able to find that solution.
So once again, if anyone knows how to approach this - I'm listening! ;-)
The <f:setPropertyActionListener> is executed during invoke action phase of the form submit. So it expects that the value is still there at that point. But since your select bean is request scoped, it isn't there during form submit anymore. You want instead to pass a request parameter which get inlined in the output during render response. You can do this with <f:param>.
<p:commandButton value="Show entries for date" action="day" />
<f:param name="date" value="#{calendarSelect.dateAsString}" />
</p:commandButton>
It'll be available as request parameter (note that it only understands Strings, due to the nature of HTTP). You could let JSF set request parameters as managed properties, but since your edit bean is view scoped, this isn't possible with #ManagedProperty. You've got to gather it yourself by ExternalContext.
String dateAsString = externalContext.getRequestParameterMap().get("date");
True, that's clumsy. I would just have used the same bean and view for this and toggle visibility of select/edit forms by rendered attribute. The edit view is after all not directly openable/bookmarkable by a simple GET, isn't it? ;)

Categories

Resources