Hi im working with jboss on a webapp. I got one page that is similar to forum page where you can post messages and reply to already posted ones. In my jsf i have three div tags one for adding new message one for listing all messages and one for viewing selected message. All the tags are embedded in and there is render attribute on every tag something like this:
<h:pannelGroup rendered="#{myController.shouldRender('add')}">
<!-- Here is my html for adding new message -->
</h:pannelGroup>
<h:pannelGroup rendered="#{myController.shouldRender('list')}">
<!-- Here is my html for listing messages -->
</h:pannelGroup>
<h:pannelGroup rendered="#{myController.shouldRender('view')}">
<!-- Here is my html for viewing message and its replys..
also there is hidden div with html for popup to post reply -->
<div id="reply">
<!-- This is hidden html that is shown when clicked reply
link in the message div below.
When shown users can add reply to the message -->
</div>
<div id="message">
<!-- Here is show the message itself -->
</div>
<div id="replyList">
<!-- Here is list replys for the message currently beeing viewed
For listing the replys i used ui:repeate and c:forEach from the jstl core
both resulting with same outcome.
In my message object i have list of replys which i load lazily...
-->
</div>
</h:pannelGroup>
My backing bean, stripped of all the annotations and rest of the code...
MyController{
String page;
public boolean shouldRender(String view){
return page.equals(view);
}
}
The page property i set with actionListener from list of menu items, before i redirect the user to the message.xhtml page i set myController's property page to the div name i want to view, so for e.g. if i click the add link i set the page = "add" and redirect to the message.xhtml. There the controller picks up the page set from outside and renders the add div.
Because i couldn't manage to get extended persistence context working, i set filter on /* to open user transaction and then merge the entity manager with that one, after the chain.DoFilter i commit my transaction. This i needed to enable lazy loading by hand..
The problem is that when i add reply message, the list with replies does not get refreshed immediately, i need to go back to the message list and then again open the same message in the view div to get the list of replies refreshed.. or... in the method for adding reply i tried to manually load my reply inside the list of replies owned by the message object (which are lazy loaded and mapped #OneToMany) and this way it works but i don't like that solution.
Can someone tell me weather hibernate is reloading the lazy loaded list because i manage the transaction and i assume that once it loaded my list, it doesn't refresh it on it's own.
When the list is modified in the same session, it is updated.
When the list is modified in a different session, it does not get updated.
As the session object is not multi-thread safe, in your environment probably every user has his own session instance, so you'll be in the second case. To force a refresh, you can evict() the parent instance and load() it again, or you clear() the session or you create and use a new one.
Pay attention with lazy loading. As the child elements are loaded on first usage (and not together with the parent instance), they can already reflect to a modification which was not yet made when the parent object was loaded.
Related
I've a tomcat application with jsf 1.1
Case:
My application has a jsp (let name it /create.jsp) that contains a form to create a Business Object (imagine type person). One of the attributes of this Business Object is a relation to itself (the BO person, has an attribute father, that is also of type person). For this porpose, in the jsp, I have a selectable, and a button. The button enables to create new Business Object (in this case, a person). Therefore, the jsp show in the popup is the same that the one shown in the main window
Problem:
I'm facing wrong behaviours in the main window.
Cause:
I've studied the case, and the reason of the problem is the ids of the views stored in the server. When the users requires a new page, the server creates a view (ViewRoot) and stores it at the session. The jsp path is used as the id of the View. When the user submits a form, it will rehuse the same view stored in the session.
The problem in my case is that the popup ViewRoot, and the main window ViewRoot share the same id. So when the main window is shown, its viewRoot will be stored (let say id /create.jsp), but, when the popup is shown, its viewRoot will overwrite the main one in session. After closing the popup, the user will try to submit the main page, but in the server, there is no such a ViewRoot.
Possible Solution:
I've been thinking on changing the ViewRoot id creation, but I thing that this is not feasible (at least if I don't modify the jsf library).
---OLD TEXT---
I have a jsp with a form (let name it /create.jsp), that opens a popup window. This popup will also use /create.jsp .
Due to that JSF view-id, is fomed by the jsp path, both pages will share same id. So when the popup is displayed, the view stored in the session for the main page is overwritten by the new one. Because of this, the application is not working properly.
Is there any way to change the ids of the views? anyone has any solution?
Thanks
You probably want to look into using a subview . You can assign a name-space within this that will essentially create a new namespace within the page. In facelets that would be:
<f:view id="main">
<ui:include "myOtherJsp.jsp" /> <!-- This containing a subview -->
</f:view>
Alternatively I think you may just need to separate the page into multiple views:
<f:view id="mainpage">
<p>Page content</p>
</f:view>
<f:view id="popup">
<p>My Popup</p>
</f:view>
I don't know the specifics of your application, but I can't see a situation where there's a reason to not have multiple views/forms. I'm guessing separation will fix your problem. You can use some elements of JSF outside the view ( so there's no reason to use a single view per page unless you're forced.
Caveat: I'm a JSF2 developer for the most part and I haven't done a JSF1.1 app in a long time.
My final solution is the following:
Create a jsp name popup_create.jsp, that only contains an inlcude to the create.jsp
Duplicate create.jsp entry in facesconfig with popup_create.jsp
Create a ViewHandler (add it in config) with an extension of ViewHandlerImpl, where createView & restoreView methods are ovewritten, so that the viewId, in case that is create.jsp, and we are in a popup, it will modify the viewId to poup_create.jsp.
As I think this may be done in a more elegant way, it is the only way I've found.
I would like to basically do what Jason asked for here
In one sentence, I would like the url bar to represent the state of the AJAX application so that I can allow to bookmark it as well as allow the user to return to the previous state by using the back/forward buttons in the browser.
The difference for me (From what Jason asked) is that I am using JSF 2.0.
I've read that JSF 2.0 added the ability to use get, but I am not sure what the correct way to use this.
Thanks for the help.
Further Clarification
If I understand correctly, to be able to bookmark specific states in the AJAX webapp I will have to use the location.hash. Am I correct? I'm trying to achieve a gmail-like behaviour in the sense that, while the app is complete AJAXified and no redirects occur, I can still use Back/Forward and bookmark (And that's why I would like the URL bar to be updated from the AJAX app itself and not through redirection)
Update
Just found this similar question
The difference for me (From what Jason asked) is that I am using JSF 2.0. I've read that JSF 2.0 added the ability to use get, but I am not sure what the correct way to use this.
Please note that this is not the same as maintaining the Ajax state. It usually happens by fragment identifiers (the part starting with # in URL, also known as hashbang). JSF doesn't offer builtin components/functionality for this. As far I have also not seen a component library which does that. You may however find this answer useful to get started with a homegrown hash fragment processor in JSF.
As to using GET requests, just use <h:link>, <h:outputLink> or even <a> to create GET links. You can supply request parameters in the h: components by <f:param>. E.g.
<h:link value="Edit product" outcome="product/edit">
<f:param name="id" value="#{product.id}" />
</h:link>
In the product/edit.xhtml page you can define parameters to set and actions to execute upon a GET request
<f:metadata>
<f:viewParam name="id" value="#{productEditor.id}" />
<f:event type="preRenderView" listener="#{productEditor.init}" />
</f:metadata>
In the request or view scoped bean associated with product/edit.xhtml page -in this example #{productEditor}-, you just define the properties and the listener method. The listener method will be executed after all properties are been gathered, converted, validated and updated in the model.
private Long id;
private Product product;
public void init() {
product = productService.find(id);
}
Normally you'd use AJAX to prevent complete page refreshes. AFAIK all current browsers would issue a page refresh if you change the base uri. Thus you would have to use the hash part as suggested in the question you provided.
We had a similar problem and did something like this:
We settled for the fact that users cannot bookmark the url.
For URLs that should be unique/bookmarkable we used different links that issue a redirect. Those URLs are provided in a sitemap.
For browser back, we added an intermediate page after login. This page does navigation and a redirect to the application. The navigation is stored in the session and when the server gets a navigation request (which can be a history back) the corresponding state is restored. A browser back opens that intermediate page which issues a redirect along with a navigation request on the server side.
I'm new to Stripes and appreciate every hint that brings me nearer to a functioning web-app!
technological setup: java, dynamic web project, stripes, jsp
scenario:
users can login (index.jsp). After correct email-adress and password (LoginFormActionBean.java), the user is forwarded to a welcoming page (loggedin.jsp).
The content on this welcoming page is something like "welcome < username >, you've been successfully logged in!".
implementation:
i have a form in the index.jsp where i take the user input and pass it to a method in the LoginFormActionBean.java --> works!
in the corresponding method i check whether the user is correct and if so, i insert the user in the ActionBeanContext:
getContext.setUser(loggedinUser);
after that i forward to the loggedin.jsp:
return new ForwardResolution("/loggedin.jsp");
the loggedin.jsp contains following important lines:
<jsp:useBean id="loggedinBean" class="mywebapp.controller.LoggedinBean" scope="session" />
...
${loggedinBean.context.user} //show the whole user object
...
<s:form beanclass="mywebapp.controller.LoggedinBean" name="ButtonForm">
<s:submit name="foo" value="PrintUser" />
</s:form>
<s:form beanclass="mywebapp.controller.LoggedinBean" name="TextForm">
<s:text name="user" />
</s:form>
...
the LoggedinBean.java contains a MyActionBeanContext attribute (like the LoginFormActionBean.java).
to get the userobject out of the context i use:
public String getUser(){
return getContext().getUser().toString();
}
furthermore the LoggedinBean.java contains a method, which is annotated with #DefaultHandler and forwards to loggedin.jsp (the same page)
result:
now, what happens is: after logging in correctly, i'm forwarded to the loggedin.jsp,
the line "${loggedinBean.context.user}" is empty and so is the < s:text >-field.
BUT after clicking the "PrintUser" Button, the < s:text >-field in the "TextForm"-form is filled with the user object of the logged in user!
conclusion:
what i think happens, is that the "setContext()" method of the LoggedinBean.java is not called before i manually execute a method in the bean. Because the "setContext()" method in the bean is not called before i press the button!
the online documentation says to use a context attribute in a JSP just write "${actionBean.context.user}". But the context is null!
even the book "pragmatic stripes"(2008) gives no more information about using the ActionBeanContext.
question:
what happens there?
how can i get the "${loggedinBean.context.user}" line to display the logged in user at all?
and how can i get the < s:text >-field to display the user object after loading the JSP, but without pressing the button?
i hope my problem is clear and my remarks are satisfying
I would like to recommend the usage of the MVC pattern. This pattern will lead to an implementation were the Action Beans will act as controllers that handle all http requests and the JSP pages will become passive views with little logic, only accessible via the Action Bean controllers (no direct access to JSP pages any more!).
If you use this pattern, you always have an "actionBean" available in your JPS and thus you can refer to ${actionBean.context} (see: getContext).
My title maybe confusing so please read on. I'm using the following technologies if you may. Spring, Hibernate, JSF (RichFaces), MySQL, Internet Explorer.
I have a List of items which is displayed in a RichFaces datatable like so:
item a
item b
item c
item d
item e
On the same page I have the following buttons: search, edit, add, delete and new.
When an user enters a search string, e.g. "item c", and press search button, then it displays a list of matching items, e.g:
item c
When the user presses the new button, the request will be redirected to another page using:
FacesContext facesContext = FacesContext.getCurrentInstance();
facesContext.getExternalContext().redirect(page + ".jsf" );
When the browser back button of IE is been pressed on that page, the page displays "web page expired". What is this and how can I avoid this?
web page expired
You will get this error when you're trying to obtain a non-cached POST request from the browser history. This behaviour is fully expected. To fix this "problem", you need to either turn the cache on or to replace POST by GET.
Enabling the browser cache is actually easy: just remove the Cache-Control: no-cache and related headers from the HTTP response of the POST request in question. The enduser will then only get a warning dialog that the POST data will be resent to the server, which in case of fully non-idempotent requests like placing an order or deleting an item is really not desirable. Replacing POST by GET is then a better solution. Getting searchresults (like as Google does) should really be done by GET.
Replacing POST by GET isn't easy in JSF prior to version 2.0. Best what you can do is to fire a redirect after the POST and pass the data of interest as request parameter which you retain from #{param} as managed property (more recommended) or store the data of interest in session scope (not recommended). A completely different alternative is to replace the JSF <h:form> by a simple HTML <form action="searchresults.jsf"> and do the search job in a #PostConstruct method in the backing bean associated with searchresults.jsf, after the submitted query has been gathered as managed property or from request parameter map.
hi i have 3 jsp pages 1.parent 2. child 3.grandChild
how can i access a radio button in grandChild jsp in Parent Jsp
can i access like this
parent.parent.document.forms['AccountClosureForm']['DECISION'][0]==true
I assume you either used page include directive or jsp include directive. I don't see any parent child relationship here. You would be able to share the whatever you have inside request or session or application scope. And I suppose you would have been using request, most probably.
From your code snippet, it looks you want to use it in JavaScript. Isn't it? If thats the case you can simply do something like document.forms["whatever"].... because its gonna be a single document on the client, no matter if you used a number of includes.
you cannot
JSP is run server side, you dont have a Javascript document on your server
If you want to have jsp 'talk' to each other you can use session and request objects
But once all 3 jsp are send to the browser and rendered as HTMl you can use any JavaScript you see fit to achieve what you want