creating a simple link that invokes a jsf method - jsf

i'm making a logout link and this is the code of the logout bean.
public void doLogout() {
try {
FacesContext.getCurrentInstance().getExternalContext().getSessionMap().put("user_info", null);
FacesContext.getCurrentInstance().getExternalContext().redirect("../index.xhtml");
} catch (Exception e) {
}
}
in my xhtml page i have
<ul class="dropdown-menu">
<li><h:outputLink value="#{logout.doLogout()}">Logout</h:outputLink></li>
</ul>
my problem is when i get into the page, the page automatically logs me out, its invoking the logout.doLogout() method without me clicking the link itself.
i tried erasing the code inside the doLogout() and just change it to simply a Sysout, and it does invoke the method with out me clicking the link.

oh stupid of me.. <h:commandLink action="logout.doLogout()">Logout</h:commandLink> does the job.

Related

JSF Request Scoped Bean not displaying data in page

I'm experimenting with JSF scopes, and have some issues when using a session scoped bean within a request scoped bean.
The basic workflow is that the user would click a View button on an item from the home page, which then calls my code to load & display that item's information.
Here's my UPDATED code:
#ManagedBean(name="itemViewBean")
#RequestScoped
class ItemViewBean {
#ManagedProperty("#{itemBean}")
private ItemBean itemBean;
private ItemViewObject itemViewObject;
private int itemId;
public void init() {
itemViewObject = itemBean.readItem(itemId);
}
public String readItem(int itemId) {
// itemViewObject = itemBean.readItem(itemId); // moved to init();
return "/pages/viewItem.xhtml?faces-redirect=true";
}
public ItemViewObject getItemViewObject() {
return itemViewObject;
}
// getters & setters as needed
}
#ManagedBean(name="itemBean")
#SessionScoped
class ItemBean {
public ItemViewObject readItem(int itemId) {
// hardcoded creating a ItemViewObject for now.
// eventually would be loaded from the database.
....
}
}
My UPDATED view page then has things like:
<!-- added the metadata -->
<f:metadata>
<f:viewParam name="id" value="#{itemViewBean.itemId}" />
<f:event listener="#{itemViewBean.init}" type="preRenderView" />
</f:metadata>
<!-- same as before -->
<h:outputText value="#{itemViewBean.itemViewObject.description}" />
If my viewBean is request scoped (or view scoped), I get empty data on the view page. If the viewBean is session scoped, things work. And I'm not understanding why?
From what I see in my debugger, readItem(itemId) is called (from the home page when clicking a view button), but when the view page itself calls the getItemViewObject(), the itemViewObject is null.
What am I doing wrong?
UPDATE
I forgot to mention earlier how my home page was calling readItem method, and that was through a command button:
<h:commandButton class="btn btn-mini firefoxBtnMiniCorrection"
value="View"
action="#{itemViewBean.readItem(b.itemId)}"/>
Each item listed in the home page has its own View button.
Also forgot to mention that both the home page and my view page are using JSF Templates. I don't know if that matters.
From the comments below which people have made, I came up with the code changes above. And things work now. Using either request scope or view scope with ItemViewBean works now.
And I am surprised this worked! I'm not quite certain I fully understand why it works.
Are my changes the correct way to do things? Or is there a better way?
Also, I'm using JSF 2.1.
Update 2
It doesn't work. The scoping works, but I discovered that the itemId in the viewParam is always null. Why?
itemViewObject is private in a RequestScoped bean. After readItem() got a value for itemViewObject, this value will be forgotten after this request and will be null at the next request (`#RequestScoped').

FacesMessage is not displayed when being set in an action method with a redirect outcome

Why the code from the first block works and the other one doesn't? It's all about displaying JSF messages
#PostConstruct
public void init() {
try {
throw new RuntimeException();
} catch (RuntimeException e) {
i18nExceptionHandler.handleException(e);
}
}
The code above works well - it displays the message.
public String login() {
try {
//login actions
} catch (AuthenticationException e) {
//this doesn't work
i18nExceptionHandler.handleException(e);
}
return "/pages/loggedin?faces-redirect=true";
}
This code doesn't work - it doesn't display any message and I'm given following error:
WARNING: There are some unhandled FacesMessages, this means not every FacesMessage had a chance to be rendered.
Why it works like that? Shall I use validator or something else on the login method (and the rest as well)?
You need to include h:messages tag in your jsf page. for example,
<h:messages id="messagesID" globalOnly="true" layout="table" />
If you don't have this in your JSF page, the warning message will arise.
Message from the second code block wasn't displayed, because method hasn't got void signature.

How to invoke a JSF bean action from a link?

We have the following requirement in our project.
On click of a link,
A JSF managed bean method should be invoked which will return a URL
to a document.
This document should be opened in a new window.
How can I do this?
How about a <h:commandLink/> with a target="_blank" attribute:
<h:commandLink action="#{bean.action}" target="_blank" value="Open document"/>
And in your bean:
public void action() {
try {
FacesContext.getCurrentInstance().getExternalContext()
.redirect("page2.xhtml");
} catch (IOException ex) {
// do something here
}
}
Replace page2.xhtml with your target url.

How to grab a local path from end-user in JSF

I'm facing a simple problem
I would like to get a local path from the end-user of my web application. I need only that and not to actually upload a file. (I know there are fileUpload tags in seam or in Primefaces but I just need the local full path as I'm uploading directly to Picasa Web Albums via the Google API)
In other words I would like to bind some kind of html tag : input type="file"
to a bean property (I notice that the JSF tag h:inputText tag doesn't have a type attribute)
Any ideas?
Env : JBoss AS 5.1, JSF1.2, Seam 2.2, Primefaces 1.1
Edit : here is my working solution
Thanks to the answers, I implemented the use-case of uploading a file directly to Picasa
<h:form prependId="false" enctype="multipart/form-data">
<s:fileUpload id="fileUpload"
data="#{picasa.incomingFile}"
contentType="#{picasa.fileType}"/>
<h:inputText id="albumId"
value="#{picasa.albumId}" />
<h:commandLink action="#{picasa.upload()}"
value="Upload">
<f:param name="s"
value="#{subjectHome.id}"/>
</h:commandLink>
</h:form>
and the component code
#Name("picasa")
public class PicasaService {
#Logger private Log log;
private PicasawebService service;
private InputStream incomingFile;
private String fileType;
private String albumId;
#Create
public void setUp()
{
service = new PicasawebService("picasaService");
try {
service.setUserCredentials("xxx#yyyy.zzz", "password");
} catch (AuthenticationException e) {
e.printStackTrace();
}
}
public void upload()
{
URL albumUrl;
PhotoEntry returnedPhoto;
try {
albumUrl = new URL("https://picasaweb.google.com/data/feed/api/user/default/albumid/" + albumId);
MediaStreamSource myMedia = new MediaStreamSource(incomingFile , this.fileType);
returnedPhoto = service.insert(albumUrl, PhotoEntry.class, myMedia);
} catch (MalformedURLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ServiceException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
This way, it seems to me that the file is not transferred twice (one from end-user machine to my web app's server and from there to picasa WA server).
Hope this helps
but I just need the local full path as I'm uploading directly to Picasa Web Albums via the Google API
You need to get the file's content as an InputStream from the JSF file upload component and write it to an FileOutputStream on the server's local disk file system the usual way, then you can reference it as a File and pass it to the Picasa API as documented.
See also:
What is the alternative of file browse in JSF?
You can't get the local path for security reasons, all modern browsers won't provide your code with that information... bestcase is they give you the file name only...

JSF how add a control on the first url

I have to implement a new feature in my existing JSF application.
As it is now, there is a feature for searching a objects. The normal flow is: fill in some form parameters and see the detailed object page after submitting the form.
Now I have to find a way to go to the detailed object page via a link which arrives through an email.
In the link there are some parameters, useful to find the object, but if the object doesn't exist I would to forward the user to a courtesy page.
How could I manage this thing?
thank you very much
Do the job in constructor or #PostConstruct method of the bean which is associated with the view and use the rendered attribute to render page fragment/include conditionally.
#PostConstruct
public void init() {
someObject = someDAO.find(someParam);
}
with
<h:panelGroup rendered="#{bean.someObject != null}">
Found
</h:panelGroup>
<h:panelGroup rendered="#{bean.someObject == null}">
Not gound
</h:panelGroup>
Or use ExternalContext#redirect() to redirect to another view.
#PostConstruct
public void init() {
someObject = someDAO.find(someParam);
if (someObject == null) {
FacesContext.getCurrentInstance().getExternalContext().redirect("notfound.jsf");
}
}

Resources