Today I'm using a servlet to receive a POST from a HTML page and then redirecting to my JSF page.
This is my actual Servlet:
public class CommInServlet extends HttpServlet {
private String reportKey;
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
req.getSession(true).setAttribute("reportKey", req.getParameter("reportkey"));
req.getRequestDispatcher("main.xhtml").forward(req, resp);
}
}
HTML post page:
<html>
<head />
<body>
<form action="Filtro" method="post">
<input type="text" size="120" name="reportkey" value="XXXXXXXXXXXX" />
<input type="submit" value="doPost" />
</form>
</body>
</html>
Is it possible to post directly to my JSF page (ManagedBean)? How?
I want to replace the Servlet for something... better.
Sure you can. Most JSF requests are POSTs anyway, so if you use the path to the JSF page you're intending to handle the POST request, you can then get the parameter within a managed bean that is backed by that page OR get the parameter within the page itself.
Within a managed bean:
#PostConstruct
public void initMyBean(){
/**This map contains all the params you submitted from the html form */
Map<String,String> requestParams = FacesContext.getCurrentInstance().getExternalContext().getRequestParameterMap();
requestParams.get("reportKey");
}
OR
within the managed bean have
#ManagedProperty(value="#{param.reportKey}")
String reportKey;
//getter and setter of course!
The method you've annotated with #PostConstruct will be executed after the managed bean has been instantiated. The above will give you access within your managed bean.
If you need the value within your page first however, you can have this in your page (preferably at the top)
<f:metadata>
<f:viewParam name="reportKey" value="#{backingBean.reportKey}" required="true"/>
</f:metadata>
Notice how you can perform validations on the parameter from within your view. Pretty cool feature.
Just be sure and set your html form action attribute to the path of the JSF view.
Related
I have a JSP which has below tags the data in resultsList fed in some action and forwarded to below jsp here I would like to get the data back into the other action based on the checkbox selection. Please help, can do using Struts1 but don't like to turn back to Struts1 since started using Struts2.
<display:table class="displaytag" id="row" style="font-size:1.4em;" name="resultsList" requestURI="/SomePath.action">
<display:column property="businessType" title="Business Type"></display:column>
<display:column property="structure" title="Structure"></display:column>
<display:column property="tradeSubType" title="Trade Sub Type"></display:column>
<display:column property="businessGroup" title="Business Group"></display:column>
<display:column title="Select To Copy" align="center">
<s:checkbox name="selectToCopy" fieldValue="false" value="false" label="Check Me To Download"></s:checkbox>
</display:column>
</display:table>
The data will be fetched in one action and forwarded to the jsp where jsp contains above display tag and now I need to submit the form and action should receive the checked information to process further. Any help here is really appreciated, I can do it using Struts1 no doubt but would like to continue in Struts2.
I'm guessing your action class sends some domain objects from this type:
public class MyData {
private Integer id;
private String businessType;
//other params
//getter/setters
}
And your action class, that ist invoked before accessing the displaytag jsp page has a list of objects form type MyData:
public class MyDisplayTagAction extends ActionSupport {
private List<MyData> myDataList;
//other params
//getter/setter
public String execute() {
myDataList = getMyDataListFromSomewhere();
return SUCCESS;
}
}
The JSP should contain a form and a submit button. Moreover you have to define every data you want to send back as a field in that form. If the user is not allowed to change them, use hidden fields. The #attr.row.id access printing that id to the value. #attr is from ognl to access the variable row defined from displaytag. (For more info: Struts OGNL)
<s:form action="myStrutsPostAction" method="post">
<display:table name="myDataList" uid="row">
<display:column>
<s:checkbox name="resultsList[%{#attr.row_rowNum - 1}].selectToCopy" id="check%{#attr.row_rowNum - 1}" value="%{#attr.row.selectToCopy}"/>
</display:column>
<display:column>
<input type="hidden" name="resultsList[<s:property value='%{#attr.row_rowNum - 1}'/>]" value="<s:property value='%{#attr.row.businessType}' />"/>
<s:property value="%{#attr.row.businessType}"/>
</display:column
</display:table>
<s:submit>
</s:form>
The post action class (the one that takes the form request) should contain a list, that was defined in the <s:form> and struts will set only the the data into this list.
public class MyPostAction extends ActionSupport {
private List<MyData> resultsList = new ArrayList<>();
//getter/setter
}
Is there a way to execute a JSF managed bean action when a page is loaded?
If that's relevant, I'm currently using JSF 1.2.
JSF 1.0 / 1.1
Just put the desired logic in the constructor of the request scoped bean associated with the JSF page.
public Bean() {
// Do your stuff here.
}
JSF 1.2 / 2.x
Use #PostConstruct annotated method on a request or view scoped bean. It will be executed after construction and initialization/setting of all managed properties and injected dependencies.
#PostConstruct
public void init() {
// Do your stuff here.
}
This is strongly recommended over constructor in case you're using a bean management framework which uses proxies, such as CDI, because the constructor may not be called at the times you'd expect it.
JSF 2.0 / 2.1
Alternatively, use <f:event type="preRenderView"> in case you intend to initialize based on <f:viewParam> too, or when the bean is put in a broader scope than the view scope (which in turn indicates a design problem, but that aside). Otherwise, a #PostConstruct is perfectly fine too.
<f:metadata>
<f:viewParam name="foo" value="#{bean.foo}" />
<f:event type="preRenderView" listener="#{bean.onload}" />
</f:metadata>
public void onload() {
// Do your stuff here.
}
JSF 2.2+
Alternatively, use <f:viewAction> in case you intend to initialize based on <f:viewParam> too, or when the bean is put in a broader scope than the view scope (which in turn indicates a design problem, but that aside). Otherwise, a #PostConstruct is perfectly fine too.
<f:metadata>
<f:viewParam name="foo" value="#{bean.foo}" />
<f:viewAction action="#{bean.onload}" />
</f:metadata>
public void onload() {
// Do your stuff here.
}
Note that this can return a String navigation case if necessary. It will be interpreted as a redirect (so you do not need a ?faces-redirect=true here).
public String onload() {
// Do your stuff here.
// ...
return "some.xhtml";
}
See also:
How do I process GET query string URL parameters in backing bean on page load?
What can <f:metadata>, <f:viewParam> and <f:viewAction> be used for?
How to invoke a JSF managed bean on a HTML DOM event using native JavaScript? - in case you're actually interested in executing a bean action method during HTML DOM load event, not during page load.
Another easy way is to use fire the method before the view is rendered. This is better than postConstruct because for sessionScope, postConstruct will fire only once every session. This will fire every time the page is loaded. This is ofcourse only for JSF 2.0 and not for JSF 1.2.
This is how to do it -
<html xmlns:f="http://java.sun.com/jsf/core">
<f:metadata>
<f:event type="preRenderView" listener="#{myController.onPageLoad}"/>
</f:metadata>
</html>
And in the myController.java
public void onPageLoad(){
// Do something
}
EDIT - Though this is not a solution for the question on this page, I add this just for people using higher versions of JSF.
JSF 2.2 has a new feature which performs this task using viewAction.
<f:metadata>
<f:viewAction action="#{myController.onPageLoad}" />
</f:metadata>
#PostConstruct is run ONCE in first when Bean Created.
the solution is create a Unused property and Do your Action in Getter method of this property
and add this property to your .xhtml file like this :
<h:inputHidden value="#{loginBean.loginStatus}"/>
and in your bean code:
public void setLoginStatus(String loginStatus) {
this.loginStatus = loginStatus;
}
public String getLoginStatus() {
// Do your stuff here.
return loginStatus;
}
Calling bean action from a <p:remoteCommand> will be a good idea, keep attribute autoRun="true"
Example below
<p:remoteCommand autoRun="true" name="myRemoteCommand" action="#{bean.action}" partialSubmit="true" update=":form" />
I am using PF3.5+JSF2.1.22 and in my web application i am using Primefaces Captcha component. I am getting some weird issue in capcha component,i used captcha component like this in application
<p:captcha id="captcha" label="Captcha" theme="white" />
And i have a PF command page to submit the values to bean
<p:commandButton id="clear" value="Clear" update="captcha" styleClass="kuberbutton" />
When i am using button like above after form submit if any validation issue and other issue coming and age is loading again then Captcha is not visible in page any more but when i am using ajax="false" in PF button then it is working,is this is behavior this component will work i have to do ajax="false"? I checked the PF website they also did same thing Primefaces Captcha
Captcha component in Primefaces currently does not support ajax behavior , that why you must use ajax="false" in your <p:commandButton , you page must be fully reloaded for the captcha to work properly...
If you must have the ajax behavior you could use some other third party solution...
Haven't tried the following, but it might help with ajax issues:
recaptcha - AJAX AP
Displaying reCAPTCHA Without Plugins
How can I load a reCaptcha form using jQuery/AJAX while leaving the reCaptcha scripts in place?
As already said Primefaces Captcha component can't be updated by ajax request. But there is a simple solution - update everything but not Captcha component itself.
Your XHTML:
<h:form id="myForm">
<h:panelGroup id="updateFormAllValuesButNotCaptcha">
Name: <p:inputText id="name" value="#{captchaBean.name}" required="true"/>
<br/>
Comment: <p:inputTextarea id="comment" value="#{captchaBean.comment}" required="true"/>
<br/>
</h:panelGroup>
<p:captcha/>
<p:commandButton value="click me" update="updateFormAllValuesButNotCaptcha"
actionListener="#{captchaBean.someAction}" oncomplete="Recaptcha.reload()"
onerror="Recaptcha.reload()"/>
</h:form>
<p:messages globalOnly="false" autoUpdate="true"/>
Your backing bean:
#ManagedBean
#ViewScoped
public class CaptchaBean implements Serializable {
private String name;
private String comment;
public String getComment() { return comment; }
public void setComment(String comment) { this.comment = comment; }
public String getName() { return name; }
public void setName(String name) { this.name = name; }
public void someAction() {
FacesMessage msg = new FacesMessage(FacesMessage.SEVERITY_INFO, "Done", "");
FacesContext.getCurrentInstance().addMessage(null, msg);
}
}
Note that I am updating updateFormAllValuesButNotCaptcha panel which contains all form input fields but not Captcha itself. It is also important to notice that Captcha can't be reused, so you have to reload it always when ajax request has been completed or ended with error.
What you update after commandButton's action succeeded is up to you. You can hide form (do not render it) and show only confirmation message to make sure user won't try to send comment again.
I'm passing a parameter p1 to another page page.xhtml:
<ui:include src="page.xhtml">
<ui:param name="p1" value="#{someObject}"/>
</ui:include>
Is this possible to evaluate #{p1} inside #PostConstruct method of the backing bean of page.xhtml? Using the following piece of code, #{p1} cannot resolve:
FacesContext currentInstance = FacesContext.getCurrentInstance();
currentInstance.getApplication().evaluateExpressionGet(currentInstance, "#{p1}", String.class);
Why do I need this?
I'm using an xhtml file (say component.xhtml) as a custom UI component. This file has a backing bean from which I should get component data. Since I'm including this xhtml file twice or more in my main JSF page, I want to pass different objects to each of component.xhtml so that my component work with my custom data each time included.
In Mojarra, you can get it as an attribute of the FaceletContext. You can get it in the #PostConstruct of a managed bean which is guaranteed to be referenced/constructed for the first time in the included page (and thus not in the parent page before the <ui:param> is declared in the component tree).
FaceletContext faceletContext = (FaceletContext) FacesContext.getCurrentInstance().getAttributes().get(FaceletContext.FACELET_CONTEXT_KEY);
Object p1 = faceletContext.getAttribute("p1");
In MyFaces, the whole FaceletContext isn't available in managed beans as it's discarded by end of view build time and this construct would then not work. To be JSF implementation independent, you might want to consider to set it via <c:set scope="request"> instead. It's then available as a request attribute.
As to the concrete functional requirement, consider creating a comoposite component with a backing component. For some examples, see our composite component wiki page and this blog about using multiple input components in a composite component. See also When to use <ui:include>, tag files, composite components and/or custom components?
The param is not available in the #PostConstruct method; you can use the preRenderComponent event to initialize the parameters inside your backing bean; just put it after the ui:composition of the included page, it will be executed before the rendering of the included page itself.
Following the OP example of a passing a p1 parameter to a page.xhtml template
the main page:
<ui:include src="page.xhtml">
<ui:param name="p1" value="#{someObject}"/>
</ui:include>
page.xhtml:
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:ui="http://java.sun.com/jsf/facelets"
...>
<ui:composition>
<f:event listener="#{backingBean.init(p1)}" type="preRenderComponent"/>
...
</ui:composition>
</html>
BackingBean.java:
#ViewScoped
public class BackingBean{
private Object p1;
public void init(Object value){
this.p1=p1;
}
...
}
the event is fired before the render of the ui:composition tag, that is before the render of page.xhtml
This works for me:
<ui:include src="page.xhtml">
<ui:param name="p1" value="#{someObject}"/>
</ui:include>
page.xhtml:
<c:set var="data" value="#{p1}" scope="request"/>
Your bean:
#ViewScoped
public class ManagedBean{
private Object someObject;
public Object getSomeObject(){
if(someObject== null){
HttpServletRequest request = (HttpServletRequest)FacesContext.getCurrentInstance().getExternalContext().getRequest();
someObject= request.getAttribute("data");
}
return someObject;
}
public void setSomeObject(Object someObject){
this.someObject = someObject;
}}
i'm trying to get a plain commandLink to work. Here is a code snippet of the page:
<div class="item-single">
<h:graphicImage value="image/screenshots/#{collectionListBean.collectionListTeaser[0].screenshot}" alt="Screenshot #{collectionListBean.collectionListTeaser[0].title}"/>
<div class="item-title">
<h:form id="teaser0">
<h:commandLink value="#{collectionListBean.collectionListTeaser[0].title}" action="#{collectionBean.showCollection(collectionListBean.collectionListTeaser[0].id)}" />
</h:form>
</div>
<div class="item-description">
<p>
<h:outputText value="#{collectionListBean.collectionListTeaser[0].persons.get(0).person.getFullName()}" />
</p>
</div>
</div>
The title is displayed correctly, so the backing bean and the list is available and accessible. CollectionBean is also available and accessible. The list has a fixed size and is used inside a javascript gallery which is the reason why i didn't use ui:repeat or h/p:dataTable elements.
I have also checked BalusC'S List of common problems
The action is not being invoked in the backing bean, I get following javascript error on the browser console:
Uncaught TypeError: Cannot read property 'teaser0:_idcl' of undefined
Here is the relevant code of the backing bean (collectionBean):
#Named("collectionBean")
#Scope("access")
#ViewController(viewIds = {ViewIds.EDIT_COLLECTION, ViewIds.SHOW_COLLECTION, ViewIds.EDIT_COLLECTION, ViewIds.METADATA_COLLECTION_ADMIN, ViewIds.EDIT_COLLECTION_EXISTING, ViewIds.COLLECTION_LIST, ViewIds.HOME})
public class CollectionBean extends CollectionBeanBase {
.
.
.
public String showCollection(long id) {
//Check if user is admin, if yes, allow to edit metadata
Authentication auth=SecurityContextHolder.getContext().getAuthentication();
this.collection = collectionService.findById(id);
if (!(auth instanceof AnonymousAuthenticationToken)){
role=auth.getAuthorities().iterator().next().getAuthority();
if(role.equalsIgnoreCase("ROLE_ADMIN")) {
this.collection.setEdit_flag(true);
return ViewIds.EDIT_COLLECTION;
}
}
return ViewIds.SHOW_COLLECTION;
}
Does anyone have an idea what the problem might be? Any hint is highly appreciated! thank you guys in advance!
This is commandLink then why are you passing value in method.
Means you can use
<f:param name="id" value="#{collectionListBean.collectionListTeaser[0].id}"/>
you can easily get that value in action.
like
public String showCollection() {
FacesContext fc = FacesContext.getCurrentInstance();
Object id = fc.getExternalContext().getRequestParameterMap().get("id");
System.out.println(id);
return ViewIds.SHOW_COLLECTION;
}
i think this is best way to do it.
I rearranged the element to wrap all of the div's affected by the jQuery gallery and now it works like a charm.