Identifying Page Load Request based on Constructor Call in JSF - jsf

I have the following scenario in my project based on JSF and RF3.3
1.Each of the operation in the application is traced. That is if user opens a certain page the information about the page is stored against the name of the user.
Now the pages can be createSomething or ModifySomething...
This both pages are linked to the same backing bean since they belong to same module.
So when I trace information of user based on constructor call I cannot store the information as to whether the bean was loaded for createSomething page or ModifySomething page.
I want to get the name of the page or something unique using which I can identify whether the bean is loaded for CreateSomething or ModifySomething.
I want to know how can I trace or log information for only a page visit.i.e. user clicked on the page but didn't performed any action.
For any action performed on the page I can easily keep a record of it..
I cannot use Javascript...
Kindly guide me.

You can get the JSF view ID by UIViewRoot#getViewId() as follows:
String viewId = FacesContext.getCurrentInstance().getViewRoot().getViewId();
// ...
It will return the view identifier which is the unique path of the view root, such as /create.xhtml or /edit.xhtml.
An alternative is to let the page invoke a page-specific <f:event type="preRenderView"> listener method. For example, only in the create page:
<f:event type="preRenderView" listener="#{bean.prepareCreate}" />
with
public void prepareCreate() {
if (!FacesContext.getCurrentInstance().isPostback()) {
entity = new Entity();
}
}

Related

Passing parameters: JSF page (form) -> ViewScoped backing bean -> JSP page (confirmation) [duplicate]

I have a browse.xhtml where I browse a list of cars and I want to view the details of the car in details.xhtml when a "View more" button is pressed. Their backing beans are #ViewScoped and are called BrowseBean and DetailsBean, respectively.
Now, I wouldn't like the user/client to see the car ID in the URL, so I would like to avoid using GET params, as presented here and here.
Is there any way to achieve this? I'm using Mojarra 2.2.8 with PrimeFaces 5 and OmniFaces 1.8.1.
Depends on whether you're sending a redirect or merely navigating.
If you're sending a redirect, then put it in the flash scope:
Faces.setFlashAttribute("car", car);
This is available in the #PostConstruct of the next bean as:
Car car = Faces.getFlashAttribute("car");
Or, if you're merely navigating, then put it in the request scope:
Faces.setRequestAttribute("car", car);
This is available in the #PostConstruct of the next bean as:
Car car = Faces.getRequestAttribute("car");
See also:
Injecting one view scoped bean in another view scoped bean causes it to be recreated
How to pass objects from one page to another page in JSF without writing a converter
Note that I assume that you're very well aware about the design choice of having two entirely separate views which cannot exist (be idempotent) without the other view, instead of having e.g. a single view with conditionally rendered content. And that you already know how exactly the view should behave when it's actually being requested idempotently (i.e. via a bookmark, shared link, by a searchbot, etc). If not, then I strongly recommend to carefully read the answer on this question: How to navigate in JSF? How to make URL reflect current page (and not previous one).
Update: in case you're not using OmniFaces, use respectively the following:
FacesContext.getCurrentInstance().getExternalContext().getFlash().put("car", car);
Car car = (Car) FacesContext.getCurrentInstance().getExternalContext().getFlash().get("car");
FacesContext.getCurrentInstance().getExternalContext().getRequestMap().put("car", car);
Car car = (Car) FacesContext.getCurrentInstance().getExternalContext().getRequestMap().get("car");

JSF web application -- opening a particular page based on url parameters

Our project uses a Web Application developed using JSF, primefaces, xhtml. Currently user can login and navigate through pages sequentially by clicking on 'action' links, like:-
index.xhtml --> login.xhtml --> classes.xhtml --> students.xhtml --> student_info.xhtml
i.e. first login --> shows the list of classes --> user selects a class --> shows the list of students in that class --> user selects a student --> shows the student info.
Each of the pages has its own 'backing bean' classes. They are instantiated as and when the user clicks through the pages.
Also, user can navigate back via certain links on each page-- say, from 'student_info' page, he/she can go back to the 'students' page.
Now requirement is: user can directly go to an inner page, say, student_info page by typing an 'url' with additional parameters, ?user=alice,?passwd=xyz, ?class=5, ?studentRollNo=15.
Also, the user should still be able to navigate back to other pages (i.e. once the page is opened, their should be no behavior difference whether the user navigated normally to student_info page or, whether he directly provided url with parameters).
My questions are:-
How to read url parameters in JSF?
Which page (or backing bean) should handle the parameters? Should it be done centrally, or, in each page (backing bean) ?
In case each page handles its relevant parameters only -- is there way to redirect remaining parameters to the next page ?
What are the best practices used in such implementations?
Note:
Actual web application is much more complex, tried to provide a simpler picture which pinpoints my problem.
new to JSF, Web App etc. Don't know if there are some JSF terminologies to describe above issues.
you can pass it by url request, and each BackingBean handle it
ex:
mypage.xhtml?myparam=test
and inject the HttpServletRequest in your BackingBean (if you are using CDI)
#Inject
HttpServletRequest request;
and get the param
#PostConstruct
public void init() {
String myparam = request.getParameter("myParam");
}
for redirect to other page you can use
public String redirect() {
return "otherPage.xhtml?faces-redirect=true&otherParam=test";
}

Load JSF page by id

I have a JSF 2.0 app where each page is stored in a cms_page table in the database. That table has the PK column cms_page_id and a URL column (which holds the SEO friendly URL).
When I display a page there is a link called About Us, which has the URL "/com/aboutus.html"
This appears in my XHTML file as:
#{cmsPage.cmsPageUrlName}/>
Which renders
About Us
As far as I know h:outputLink cannot be used to fire any methods in the backing bean.
I can't use h:commandLink, as this will not show the "/com/aboutus.html" URL when you hover over the link. I can't figure out how to fire a backing bean method to navigate to the next page.
The about us link would really be going to /faces/pages.xhtml, but would use PrettyFaces to display the "/com/aboutus.html" URL
Also, what would I to if I went directly to the URL www.test.com/com/aboutus.html?
This URL doesn't exist, the actual URL would be www.test.com/faces/pages.xhtml?url=%2Fcom%2Faboutus.html
Should I be looking at setting up PrettyFaces to do all the work instead?
create Databaseconnection
read column from the database
write the column into your jsf page
please take a look at JSF/JPA documentations or tutorials to solve this.
<ui:include src="#{cmsPage._url}" />
ManagedBean Name
#ManagedBean(name="cmsPage")
#SessionScoped
class Cms_Page{
private String _pageId;
private String _url;
//getter setter
}
Use Custom method to fetch from DAO and set the values inside Cms_Page

send bean data from one jsf facelet to another

I have a table in my jsf application with some data from the database. I have made the id values a link, and my goal is to pass the data from the selected row to another facelet. How can I do this? The href I have is:
<td>#{product.id}</td>
So the goal is that when the user clicks the link, the editOrDeletePage is displayed, and I want the editOrDeletePage to "ingest" the product id, so that it knows what data to display? How can I do this?
If you definetely want to use static links, you may, of course, just read a request parameter from a target page using some kind of event listener
<f:event listener="#{bean.preRender}" type="preRenderView" />
And read the parameter from request:
FacesContext facesContext = FacesContext.getCurrentInstance();
String productId = (String) facesContext.getExternalContext().
getRequestParameterMap().get("productid");
But it's not really a JSF way to handle navigation, I belive. You may want to use commandLink or some other way of handling user actions. Or maybe, even better, think of using data table, where a user can choose a row, and you can process selection.

Audit trail for JSF application - Global valueChangeListener possible?

I am trying to implement an audit trail functionality for my web application that records:
lastModified (timestamp)
modifiedBy (user information)
userComment (reason for value change)
for each of my input fields (input fields are spread over several forms with different backing beans and different valueHolder classes).
The first two (lastModified and modifiedBy) are easily done with the help of an JPA AuditListener and #PrePersit and #PreUpdate methods.
The third one is a bit tricky since it requires user interaction. Best would be a dialog that asks for the user comment.
So there are (at least) two open issues: Can I establish a "global" valueChangeListener for all input fields in my application? Is this possible without attaching <f:valueChangeListener> to each single input component? Second: How can I grab the user comment. My idea is to put a p:dialog in my web page template but this dialog needs to know from which input component it is called.
Can I establish a "global" valueChangeListener for all input fields in my application? Is this possible without attaching to each single input component?
Yes, with a SystemEventListener which get executed during PreRenderViewEvent. You need to walk through the component tree as obtained by FacesContext#getViewRoot() to find all components which are an instanceofEditableValueHolder (or something more finer-grained) and then add the new YourValueChangeListener() by the addValueChangeListener() method. See also this answer how to register the system event listener: How to apply a JSF2 phaselistener after viewroot gets built?
Second: How can I grab the user comment. My idea is to put a p:dialog in my web page template but this dialog needs to know from which input component it is called.
You could in YourValueChangeListener#processValueChange() set the component in question as a property of some request or view scoped which you grab by evaluateExpressionGet().
Recorder recorder = (Recorder) context.getApplication().evaluateExpressionGet(context, "#{recorder}", Recorder.class);
recorder.setComponent(event.getComponent());
// ...
It will execute the EL and auto-create the bean in its scope if necessary. The bean in turn should also hold the property representing the user comment. Finally, you can use it in your <p:dialog>.
<p>You have edited #{recorder.component.label}, please mention the reason:</p>
...
<h:inputText value="#{recorder.comment}" />

Resources