JSF page redirect inside property getter - jsf

I have a JSF 2 application that retrieves data from the database and displays it on a page.
I have a property get method called "getCurrentPage" which will display the database data. Inside this method if no data exists for the specified page, I want to redirect to a 404 page.
I tried
FacesContext.getCurrentInstance().getExternalContext().redirect("404.xhtml");
but I get a java.lang.IllegalStateException.
How to I redirect?
Here is my XHTML snippet
<h:panelGroup layout="block">
<h:outputText escape="false" value="#{common.currentPage.cmsPageBody}"/>
</h:panelGroup>
Here is my bean snippet
public CmsPage getCurrentPage() {
HttpServletRequest request = (HttpServletRequest) (FacesContext.getCurrentInstance().getExternalContext().getRequest());
try {
String requestUrl = (String) request.getAttribute("javax.servlet.forward.request_uri");
if (this.currentCmsPage == null) {
// Page not found. Default to the home page.
this.currentCmsPage = cmsPageBL.getCmsPage("/en/index.html", websiteId);
} else {
this.currentCmsPage = cmsPageBL.getCmsPage(requestUrl, websiteId);
}
if (this.currentCmsPage == null) {
FacesContext.getCurrentInstance().getExternalContext().redirect("404.xhtml");
}
}
} catch (Exception ex) {
log.error("getCurrentPage Exception: ", ex);
}
return currentCmsPage;
}
}

Thou should not perform business logic in getter methods. It's only recipe for trouble in all colors. Getter methods are supposed to solely return already-prepared properties. Just use a pre render view event listener instead.
E.g.
<f:event type="preRenderView" listener="#{common.initCurrentPage}" />
<h:panelGroup layout="block">
<h:outputText escape="false" value="#{common.currentPage.cmsPageBody}"/>
</h:panelGroup>
with
public void initCurrentPage() throws IOException {
ExternalContext ec = FacesContext.getCurrentInstance().getExternalContext();
String requestUrl = (String) ec.getRequestMap().get(RequestDispatcher.FORWARD_REQUEST_URI);
if (currentCmsPage == null) {
// Page not found. Default to the home page.
currentCmsPage = cmsPageBL.getCmsPage("/en/index.html", websiteId);
} else {
currentCmsPage = cmsPageBL.getCmsPage(requestUrl, websiteId);
}
if (currentCmsPage == null) {
ec.redirect(ec.getRequestContextPath() + "/404.xhtml");
}
}
public CmsPage getCurrentPage() {
return currentCmsPage;
}
Note that I also improved some poor logic.

Related

p:dialog not able to populate values

Have made an ajax call to method which sets the String value in the bean.
var url = contextPath+'/SlCustomObjectCalls?stCallType=attachmentList&stMandDocumentName='+stMandDocumentName;
$.ajax({
type: 'POST',
url: url,
dataType: 'json',
success: function(data) {
dlg1.show();
}
});
This sets the value in the String [] attachmentList.
public class AttachmentViewHelper {
String[] attachmentList;
public String[] getAttachmentList() {
return attachmentList;
}
public void setAttachmentList(String[] attachmentList) {
this.attachmentList = attachmentList;
}
public void getAttachments(){
try {
String stDocCode = "someval";
String stProcCode = "";
String stDocNumber ="";
String stComapny = "";
// gets String []
attachmentList = getListOfAttahments(stDocCode);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
and on success ajax opens the dialog box, where i want to display the values of the attachment list.
<p:dialog id="downloadAttachemntDiag" header="Download" widgetVar="dlg1" width="300" height="200" resizable="false" draggable="false"
modal="true">
<div id="attachment">#{AttachmentViewHelper.attachmentList}</div>
Now the problem that I am facing is, the dialog box does not show any value.
Have tried using c:foreach and ui:repeat,But it didnt work.
Thank you in advance.
I don't know about the ajax call you did.
However one thing I know is that your dialog is initially sent with an empty list an never updated.
So since I don't really know vanilla ajax in jsf you could use the ajax tag or the update attribute of primefaces.
<p:commandButton ... update="downloadAttachemntDiag"/>

Bean method not called unless I remove Rendered attribute in p:commandButton in p:dataTable

I can only get my actionListener to fire if I remove my "rendered" attribute on my p:commandButton in my data table. Not sure what the problem is.
Page Code:
<ui:define name="content">
<H1>Manage Delegates</H1>
<P>In order to raise requests on behalf of other users in the system, and to be able to access, attach and update
personal information such as travel details and credit card details, you must be authorised to act on the users
behalf.</P>
<P>Please use the button below to as a user for their permission to act on their behalf within the Admin Direct
system.</P>
<h:form id="delegateForm">
<h:messages id="generalMessages"></h:messages>
<p:growl id="messages"></p:growl>
<H1>Your Delegate Requests (The users you can act on behalf of in Admin Direct)</H1>
<P>The following list represents the users you have requested to be a delegate form, and the status of those requests. You will be able to create tasks and edit the personal details of these users if your request has been Approved, and if they have authorised you to (1) create tasks for them in the system, and (2) edit their personal details.</P>
<P>If you wish to act on behalf of someone else within Admin Direct, please request delegate access using the "Request Delegate" button below. You can monitor the status of the request from here, but will also receive email confirmation once a response (Approve/Reject) has been received within the system.</P>
<P>Once a request has been approved, you will be able to select that user when creating tasks to indicate that the task is being created for someone else, but you will be able to specify that you are the primary contact during the tasks processing.</P>
<p:commandButton id="createDelegateRequest" value="Request Delegate Access" onclick="peopleDlg.show();" type="button" />
<P/>
<p:dataTable id="sentRequests" rowKey="#{sentRequest.id}" var="sentRequest"
value="#{delegateBean.user.delegateRequestsRaisedBy}">
<p:column headerText="Request Sent" style="width:100px">
<h:outputText value="#{sentRequest.createdDate}" />
</p:column>
<p:column headerText="Delegate" style="width:200px">
<h:outputText value="#{sentRequest.adminDirectUser.fullName}" />
</p:column>
<p:column headerText="Request Status" style="width:100px">
<h:outputText value="#{sentRequest.delegateRequestStatus.status}" />
</p:column>
<p:column headerText="Response Date" style="width:100px">
<h:outputText value="#{sentRequest.responseDate}" />
</p:column>
<p:column headerText="Can Raise Requests" style="width:100px">
<p:selectBooleanCheckbox value="#{sentRequest.canRaiseTasks}" disabled="true"/>
</p:column>
<p:column headerText="Can Edit Personal Details" style="width:100px">
<p:selectBooleanCheckbox value="#{sentRequest.canEditPersonalDetails}" disabled="true" />
</p:column>
<p:column headerText="Resend Email" style="width:100px">
<p:commandButton
id="resendRequest"
rendered="#{delegateBean.requestIsPending(sentRequest) or delegateBean.requestIsRejected(sentRequest)}"
value="Resend Request"
immediate="true"
process="#this"
update="#all"
actionListener="#{delegateBean.resendRequest(sentRequest)}" />
</p:column>
<p:column headerText="Delete Delegate" style="width:100px">
<p:commandButton
actionListener="#{delegateBean.deleteDelegateRequest(sentRequest)}"
value="Delete Delegate"
immediate="true"
process="#this"
update="#all" />
</p:column>
</p:dataTable>
<P/>
<P/>
<P/>
<H1>Your Designated Delegates (The people who can currently act on your behalf within Admin Direct)</H1>
<P>Any requests marked as "Approved", are employees you have authorised to act on your behalf within Admin Direct. Below you can see who is able to act on your behalf, and the permissions you have granted to these users.</P>
<P>Any requests marked "Pending", are outstanding requests which you can either Approve or Reject directly using the links provided</P>
<P>You can remove a delegate completely from the list below to prevent them from performing any actions on your behalf, or you can adjust the permissions that you have granted individuals by ticking/unticking the relevant boxes against each user.</P>
</h:form>
<p:dialog id="peopleDialog" widgetVar="peopleDlg" appendToBody="true">
<h:form id="pdSearch2">
<ps:personSearch searchButtonLabel="Find Users" searchFieldLabel="Surname: " rows="8" pagination="true" />
<p:commandButton value="Add User"
actionListener="#{delegateBean.raiseDelegateRequest(personSearchBean.selectedPerson)}"
update=":delegateForm :messagesDialogForm" oncomplete="handleAddToRoleComplete(xhr, status, args)" />
</h:form>
</p:dialog>
<p:dialog header="Admin Direct Message" widgetVar="messagesDialog" modal="true" closable="false" closeOnEscape="true"
resizable="false" height="150" width="300" appendToBody="true">
<h:form id="messagesDialogForm">
<h:outputText id="dialogMessage" value="#{delegateBean.dialogMessage}" style="text-align:centre;" />
<p />
<div style="text-align: center;">
<p:commandButton value="Close" onclick="messagesDialog.hide();"></p:commandButton>
</div>
</h:form>
</p:dialog>
<script type="text/javascript">
function handleAddToRoleComplete(xhr, status, args) {
if (args.error == true) {
messagesDialog.show();
}
}
</script>
</ui:define>
</ui:composition>
The offending item is here:
<p:column headerText="Resend Email" style="width:100px">
<p:commandButton
id="resendRequest"
rendered="#{delegateBean.requestIsPending(sentRequest) or delegateBean.requestIsRejected(sentRequest)}"
value="Resend Request"
immediate="true"
process="#this"
update="#all"
actionListener="#{delegateBean.resendRequest(sentRequest)}" />
</p:column>
my backing bean looks like this:
#ManagedBean
#ViewScoped
public class DelegateBean {
#ManagedProperty("#{sendMailBean}")
private SendMailBean sendMailBean;
private String dialogMessage = null;
private PersonSearchBean personSearchBean = null;
private UserSessionBean userSessionBean = null;
private AdminDirectUser sessionUser = null;
private DelegateRequestStatus pendingStatus = null;
private DelegateRequestStatus approvedStatus = null;
private DelegateRequestStatus rejectedStatus = null;
#PostConstruct
public void init() {
HttpServletRequest req = (HttpServletRequest) FacesContext.getCurrentInstance().getExternalContext()
.getRequest();
userSessionBean = (UserSessionBean) req.getSession().getAttribute("userSessionBean");
sessionUser = userSessionBean.getCurrentUser();
}
public void raiseDelegateRequest(PeopleServicePerson peopleServicePerson) {
AdminDirectUser requester = this.getUser(); // fresh database pull
RequestContext context = RequestContext.getCurrentInstance();
if (requester == null) {
context.addCallbackParam("error", true); // basic parameter
dialogMessage = "An issue occured locating your account details.";
setErrorMessage(dialogMessage);
return;
}
String server = FacesContext.getCurrentInstance().getExternalContext().getRequestServerName();
int port = FacesContext.getCurrentInstance().getExternalContext().getRequestServerPort();
String app = FacesContext.getCurrentInstance().getExternalContext().getRequestContextPath();
if (peopleServicePerson == null) {
context.addCallbackParam("error", true); // basic parameter
dialogMessage = "An issue occured, the person you tried to select appears to be null.";
setErrorMessage(dialogMessage);
return;
}
AdminDirectUser adUser = getAdUser(peopleServicePerson);
if (adUser == null) {
context.addCallbackParam("error", true); // basic parameter
dialogMessage = "An issue occured, unable to locate the person in the people directory.";
setErrorMessage(dialogMessage);
return;
}
// if we get this far we can raise the request, but we need to check if
// we already have a request for this person
List<DelegateRequest> requestsRaised = requester.getDelegateRequestsRaisedBy();
if (requestsRaised != null && !requestsRaised.isEmpty()) {
// do we already have a request for this user
for (DelegateRequest request : requestsRaised) {
if (request.getAdminDirectUser().equals(adUser)) {
// we have already raised a request for this user
context.addCallbackParam("error", true); // basic parameter
dialogMessage = "You have already raised a request for this user,"
+ adUser.getFullName()
+ ". If you need to resend the existing request please use 'Resend Request option in you existing requests list.";
setErrorMessage(dialogMessage);
return;
}
}
}
// if we get this far, we have an adUser persisted in the database who
// we have yet to raise a request for
// so we can raise the request
DelegateRequest request = new DelegateRequest();
request.setCanRaiseTasks(false);
request.setDelegateRequestStatus(this.getPendingStatus());
request.setCreatedDate(new Date());
request.setRaisedBy(requester);
request.setAdminDirectUser(adUser);
requester.getDelegateRequestsRaisedBy().add(request);
request.persist();
requester.merge();
String url = "http://" + server + ":" + port + app + "/pages/customer/delegateResponseForm.jsf?requestId="
+ request.getId();
System.out.println("url " + url);
sendMailBean.sendDelegateRequest(request);
setMessage("Request for delegate access has been sent to " + adUser.getFullName());
}
private AdminDirectUser getAdUser(PeopleServicePerson peopleServicePerson) {
// Here we need to check if the user exists as an Admin Direct user
// already.
// If so then we just need to return that user.
// If not, then we need to get a full response from the people search
// service, and create a new Admin Direct User
// with the people search details used to do an initial population
// and return the persisted Admin Direct User
AdminDirectUser adUser = null;
if (peopleServicePerson != null) {
adUser = AdminDirectUser.findAdminDirectUserByPrid(peopleServicePerson.getPrid().toLowerCase().trim());
if (adUser == null) {
// Create a new AdminDirectUser instance
adUser = new AdminDirectUser();
// and get a handle on all the details from the people search
// person
PeopleServicePerson fullServicePerson = personSearchBean.findPersonFull(peopleServicePerson.getPrid()
.toLowerCase().trim());
if (fullServicePerson != null) {
adUser.setFirstName(fullServicePerson.getFirstName());
adUser.setLastName(fullServicePerson.getLastName());
adUser.setCostCentre(fullServicePerson.getCostCentre());
adUser.setDeskLocation(fullServicePerson.getRoom());
adUser.setTelephone(fullServicePerson.getOfficePhone());
adUser.setManager(fullServicePerson.getManager());
adUser.setLogonId(fullServicePerson.getPrid());
adUser.setPrid(fullServicePerson.getPrid());
adUser.setEmail(fullServicePerson.getEmail());
adUser.setEmployeeNumber(fullServicePerson.getEmployeeNumber());
adUser.persist();
}
}
}
return adUser;
}
public boolean requestIsPending(DelegateRequest request) {
// is the request passed in in pending status
System.out.println("request id: " + request.getId() + " isPending = " + request.getDelegateRequestStatus().equals(this.getPendingStatus()));
return request.getDelegateRequestStatus().equals(this.getPendingStatus());
}
public boolean requestIsRejected(DelegateRequest request) {
// is the request passed in in pending status
System.out.println("request id: " + request.getId() + " isRejected = " + request.getDelegateRequestStatus().equals(this.getRejectedStatus()));
return request.getDelegateRequestStatus().equals(this.getRejectedStatus());
}
public void abc() {
System.out.println("abc");
}
public void resendRequest(DelegateRequest request) {
AdminDirectUser requester = this.getUser(); // fresh database pull
System.out.println("Resending request");
RequestContext context = RequestContext.getCurrentInstance();
if (requester == null) {
context.addCallbackParam("error", true); // basic parameter
dialogMessage = "An issue occured locating your account details.";
setErrorMessage(dialogMessage);
return;
}
String server = FacesContext.getCurrentInstance().getExternalContext().getRequestServerName();
int port = FacesContext.getCurrentInstance().getExternalContext().getRequestServerPort();
String app = FacesContext.getCurrentInstance().getExternalContext().getRequestContextPath();
AdminDirectUser adUser = request.getAdminDirectUser();
if (adUser == null) {
context.addCallbackParam("error", true); // basic parameter
dialogMessage = "An issue occured, unable to locate the person within Admin Direct.";
setErrorMessage(dialogMessage);
return;
}
request.setDelegateRequestStatus(this.getPendingStatus());
request.persist();
String url = "http://" + server + ":" + port + app + "/pages/customer/delegateResponseForm.jsf?requestId="
+ request.getId();
System.out.println("url " + url);
sendMailBean.sendDelegateRequest(request);
setMessage("Request for delegate access has been re-sent to " + adUser.getFullName());
}
private void setMessage(String strMessage) {
FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(strMessage));
}
private void setErrorMessage(String errorMessage) {
FacesContext.getCurrentInstance().addMessage(null,
new FacesMessage(FacesMessage.SEVERITY_ERROR, errorMessage, null));
}
public String getDialogMessage() {
return dialogMessage;
}
public void setDialogMessage(String dialogMessage) {
this.dialogMessage = dialogMessage;
}
public AdminDirectUser getSessionUser() {
return sessionUser;
}
public AdminDirectUser getUser() {
AdminDirectUser adUser = null;
if (sessionUser != null) {
adUser = AdminDirectUser.findAdminDirectUser(sessionUser.getId());
}
return adUser;
}
public DelegateRequestStatus getPendingStatus() {
if (pendingStatus != null) {
return pendingStatus;
} else {
for (DelegateRequestStatus status : DelegateRequestStatus.findAllDelegateRequestStatuses()) {
if (status.getStatus().equals(DelegateRequestStatusList.PENDING.toString())) {
pendingStatus = status;
}
}
}
return pendingStatus;
}
public DelegateRequestStatus getApprovedStatus() {
if (approvedStatus != null) {
return approvedStatus;
} else {
for (DelegateRequestStatus status : DelegateRequestStatus.findAllDelegateRequestStatuses()) {
if (status.getStatus().equals(DelegateRequestStatusList.APPROVED.toString())) {
approvedStatus = status;
}
}
}
return approvedStatus;
}
public DelegateRequestStatus getRejectedStatus() {
if (rejectedStatus != null) {
return rejectedStatus;
} else {
for (DelegateRequestStatus status : DelegateRequestStatus.findAllDelegateRequestStatuses()) {
if (status.getStatus().equals(DelegateRequestStatusList.REJECTED.toString())) {
rejectedStatus = status;
}
}
}
return rejectedStatus;
}
public SendMailBean getSendMailBean() {
return sendMailBean;
}
public void setSendMailBean(SendMailBean sendMailBean) {
this.sendMailBean = sendMailBean;
}
}
This is the code which never gets called unless I remove the rendered attribute:
public void resendRequest(DelegateRequest request) {
AdminDirectUser requester = this.getUser(); // fresh database pull
System.out.println("Resending request");
RequestContext context = RequestContext.getCurrentInstance();
if (requester == null) {
context.addCallbackParam("error", true); // basic parameter
dialogMessage = "An issue occured locating your account details.";
setErrorMessage(dialogMessage);
return;
}
String server = FacesContext.getCurrentInstance().getExternalContext().getRequestServerName();
int port = FacesContext.getCurrentInstance().getExternalContext().getRequestServerPort();
String app = FacesContext.getCurrentInstance().getExternalContext().getRequestContextPath();
AdminDirectUser adUser = request.getAdminDirectUser();
if (adUser == null) {
context.addCallbackParam("error", true); // basic parameter
dialogMessage = "An issue occured, unable to locate the person within Admin Direct.";
setErrorMessage(dialogMessage);
return;
}
request.setDelegateRequestStatus(this.getPendingStatus());
request.persist();
String url = "http://" + server + ":" + port + app + "/pages/customer/delegateResponseForm.jsf?requestId="
+ request.getId();
System.out.println("url " + url);
sendMailBean.sendDelegateRequest(request);
setMessage("Request for delegate access has been re-sent to " + adUser.getFullName());
}
Any advice appreciated.
Regards
Stephen

JSF Dynamic Rendered Component's Value becomes null when the form is submitted

I have a JSF page which renders a text field depending on the value of a drop down using primefaces ajax listner. The dynamic rendering is done fine. but the problem is once I submit the form the the bound value of that textfield doesn't get bound instead it is shown as null.
this is the part of my JSF only the necessary fields are included here
<h:panelGroup id="textPanel" >
<h:form id="main" prependId="false">
<h:outputText value="WorkFlow ID:" />
<h:selectOneMenu id="workFlows" value="#{workFlowSelectionController.selectedWorkFlowId}" >
<p:ajax event="change" listener="#{workFlowSelectionController.dropDownChange}" update="textPanel"/>
<f:selectItems value="#{workFlowSelectionController.allActiveworkFlows}"/>
</h:selectOneMenu>
<p:inputText value="#{workFlowSelectionController.texField}" rendered="#{workFlowSelectionController.textfieldVisibility}"/>
<p:commandButton ajax="false" value="Next" action="#{workFlowSelectionController.addWorkFlowselectionDetails}"/>
</h:form>
</h:panelGroup>
this is my managed bean
#ManagedBean
#RequestScoped
public class WorkFlowSelectionController {
private boolean textfieldVisibility = false;
private String texField;
public void dropDownChange() {
logger.info("WorkFlowSelectionController.dropDownChange() entered");
if (selectedWorkFlowId != null) {
if (selectedWorkFlowId.equals("-1")) {
textfieldVisibility = true;
operationListStatus = false;
} else {
textfieldVisibility = false;
operationListStatus = true;
}
} else {
textfieldVisibility = false;
operationListStatus = true;
}
public void addWorkFlowselectionDetails() throws CloneNotSupportedException {
System.out.println("Selected Value of Text Field is" + texField);
}
public String getTexField() {
return texField;
}
public void setTexField(String texField) {
this.texField = texField;
}
}
i haven't included the dropdown code of the backing bean. i just need an idea of what i am doing wrong here if i remove the rendered attribute of the textfield it works fine.
thank you
Put the bean in the view scope instead of request scope. A request scoped is recreated on every single HTTP request. The boolean property will default to false again whenever you submit the form, so the submitted value won't be processed then.
#ManagedBean
#ViewScoped
public class WorkFlowSelectionController {
//
}
A view scoped bean will live as long as you're (ajax-) interacting with the same view by returning null or void from action(listener) methods.

JSF PrimeFaces FileDownload problem

I'm using PrimeFaces for a new project and it's quite an impressive set of components.
Anyway, I have problem with "real world" use of filedownload component.
In my page I have a datalist that shows the attachments related to a particular document, and I want provide a link to directly download that file inside the datalist item.
Here's my xhtml code:
<p:dataList id="ListaAllegati" value="#{documentBean.documento.allegati}" type="definition" var="attach" style="border: none" ">
<f:facet name="description">
<h:outputText value="#{attach.name}" />
<p:commandLink ajax="false" title="Download" action="#{documentBean.selectAttach}>
<h:graphicImage style="margin-left: 10px; border: none" value="./images/article.png" height="24" width="24" ></h:graphicImage>
<p:fileDownload value="#{documentBean.downloadFile}"/>
<f:setPropertyActionListener target="#{documentBean.selectedAttach}" value="#{attach}" />
</p:commandLink>
</f:facet>
</p:dataList>
and the relative java bean (request scoped):
private StreamedContent downloadFile;
public StreamedContent getDownloadFile() {
log.info("getter dell'allegato invocato");
InputStream stream = null;
byte[] rawFile = null;
if (selectedAttach == null) {
log.warn("Nessun allegato passato");
return null;
} else {
try {
log.info("Recupero del file " + selectedAttach.getGuid());
rawFile = attachManager.retrieveFile(selectedAttach.getGuid());
} catch (Exception e) {
String msg = "Errore durante il recupero del file";
log.error(msg, e);
FacesMessage fmsg = new FacesMessage(msg, "");
FacesContext.getCurrentInstance().addMessage(null, fmsg);
}
stream = new ByteArrayInputStream(rawFile);
DefaultStreamedContent file = new DefaultStreamedContent(stream,
selectedAttach.getMimeType(), selectedAttach.getName());
return file;
}
}
public void selectAttach() {
log.info("commandLink action invocata");
}
private Allegato selectedAttach;
public Allegato getSelectedAttach() {
return selectedAttach;
}
public void setSelectedAttach(Allegato selectedAttach) {
log.info("Allegato selezionato");
if (selectedAttach==null) log.warn("L'allegato passato รจ nullo");
this.selectedAttach = selectedAttach;
}
So, couple of question:
Am I doing the right thing trying to pass the selected attachment that way? Otherwise, how can I pass a parameter to tell the bean wich attachment has been clicked?
Why the first time I click the command link, nothing happen? It make a roundtrip with server, but nothing happens. Second time, it gives me an exception.
Why documentBean.selectAttach is never called and the documentBean.selectedAttach property is never set (neither the second time)?
Thanks to anyone for any hint
How to get the row object from the datatable is answered in this question:
How can I pass selected row to commandLink inside dataTable?
This answers basically all the three questions.
As to the exception in the second click, that's likely because you didn't return from the catch block when an exception is been thrown in your getDownloadFile() method. You're continuing the remnant of the code flow while the rawFile is still null. Fix it accordingly as well. Add a return null to the end of catch or something. Better yet, you should be posting the entire stacktrace in the question as you don't seem to be able to understand it. It basically already contains the answer :)
Primefaces has its own dedicated servlet for file download and upload components that handle all of this asynchronously.
Try doing something like what I have in my code
<p:commandLink ajax="false" actionListener="#{managedBean.downloadAction(object)}">
<span class="ui-icon icoFolderGo" style="padding-right: 1.5em;" />
<p:fileDownload value="#{managedBean.downloadContentProperty}" />
</p:commandLink>
And in the managed bean,
public void downloadAction(Object object) {
try {
InputStream stream = // get input stream from argument
this.setDownloadContentProperty(new DefaultStreamedContent(stream, "application/pdf", "filename.pdf");
} catch (Exception e) {
log.error(e);
}
}
public void setDownloadContentProperty(StreamedContent downloadContentProperty) {
this.downloadContentProperty = downloadContentProperty;
}
public StreamedContent getDownloadContentProperty() {
return downloadContentProperty;
}

Using kaptcha with JSF

I'm trying to use http://code.google.com/p/kaptcha/ which looks like a very easy way to include CAPTCHA. My demo app is JSF and although the instructions are simple for JSP, I don't know how to use them in JSF. How do I translate this in JSF?
In your code that manages the submit action:
String kaptchaExpected = (String)request.getSession()
.getAttribute(com.google.code.kaptcha.Constants.KAPTCHA_SESSION_KEY);
String kaptchaReceived = request.getParameter("kaptcha");
if (kaptchaReceived == null || !kaptchaReceived.equalsIgnoreCase(kaptchaExpected))
{
setError("kaptcha", "Invalid validation code.");
}
I tried putting it in my:
public String button1_action() {
// TODO: Process the action.
return "success";
}
but it doesn't understand the request object :(
This equivalent JSF action should do it:
// bind to <h:inputText value="#{thisbean.kaptchaReceived}" />
private String kaptchaReceived;
public String getKaptchaReceived() {
return kaptchaReceived;
}
public void setKaptchaReceived(String kaptcha) {
kaptchaReceived = kaptcha;
}
public String button1_action() {
if (kaptchaReceived != null) {
FacesContext context = FacesContext
.getCurrentInstance();
ExternalContext ext = context.getExternalContext();
Map<String, Object> session = ext.getSessionMap();
String kaptchaExpected = session
.get(com.google.code.kaptcha.Constants.KAPTCHA_SESSION_KEY);
if (kaptchaReceived.equalsIgnoreCase(kaptchaExpected)) {
return "success";
}
}
return "problem";
}
This assumes that you want to use h:inputText and h:graphicImage in your JSF view instead of HTML elements.
Implementing validator is another easy way to validate the kaptcha.
<h:inputText id="kaptcha" autocomplete="off" required="true">
<f:validator validatorId="kaptchaValidator" />
</h:inputText>
<h:message for="kaptcha" styleClass="errorMessage"/>
--- Validator ---
public class KaptchaValidator implements Validator {
#Override
public void validate(FacesContext facesContext, UIComponent uiComponent, Object value) throws ValidatorException {
HttpSession session = (HttpSession) facesContext.getExternalContext().getSession(true);
String kaptchaExpected = (String) session.getAttribute(com.google.code.kaptcha.Constants.KAPTCHA_SESSION_KEY);
String kaptchaReceived = (String) value;
if (kaptchaReceived == null || !kaptchaReceived.equalsIgnoreCase(kaptchaExpected)) {
FacesMessage message = new FacesMessage();
message.setDetail("Invalid Security Code.");
message.setSummary("Invalid security code.");
message.setSeverity(FacesMessage.SEVERITY_INFO);
throw new ValidatorException(message);
}
}
You can retrieve the request object from the JSF External Context, which is accessible from the FacesContext, using the following code:
HttpServletRequest request = (HttpServletRequest) FacesContext.getCurrentInstance().getExternalContext().getRequest();
Edit (thanks to McDowell) :
Another way is to use the FacesContext.getCurrentInstance().getExternalContext().getRequestParameterMap() method to access the request parameters...

Resources