Our problem is a very basic, simple implementation of editing the database using JSF + EJB.
Keeping things short:
two separate XHTML views, use two separate Managed Beans #RequestScope.
WebuserListBean and EditWebuserBean, and with #ManagedProperty we inject WebuserListBean, so we could obtain selected user data. So far no problems. Views are filled with data succesfully!
BUT!
We want to be able to edit the user!
And here (to my surprise) we cannot overcome the problem.
1st try:
Because the request scoped bean is dead after filling the view, on Save() method the #PostConstruct tries to launch again, of course it can't. So we couldn't even obtain it from database or anything.
2nd try:
Because the request scoped bean is dead after filling the view, if we do not set up user as field in #postconstruct, we lose our connection with user object which was linked on previous view (and injected, but now that view is dead too).
3rd try:
Cannot inject RequestScope in ViewScoped
Ok and our restrictions, because we think it's wrong way:
We dont want to create a SessionScoped Managed Bean for this
We dont want to use any params etc. We want to use EJB
We are not sure if we could store data in Stateful session bean which is our
endpoint for the module? Is it proper approach?
Thanks for any advice, we could paste some code but i guess it is pointless!
Cheers!
There are many ways to do it, but I recommend using the flash if the pages involved in the navigation are in the same folder (I recently found out reading a BalusC answer that there is a known issue with the flash, in which it will not hold values when navigating between pages in different folders!).
The flash is a way to hold parameters for a little longer than the context of a single request (concept taken from Ruby if I'm not mistaken, someone correct me if I'm wrong), allowing for the sent parameters to be fetched in a subsequent view, for example. Those values are discarded in the second request issued after saving them, if I'm not mistaken. You can inject the flash in your managed beans like this:
#ManagedProperty("#{flash}")
private Flash flash;
public void setFlash(Flash newFlash) {
flash = newFlash;
}
Then, you access it like a map with the put and get methods. If you use the put method in a bean, return a redirection rule and, on the second bean, use the get method your object should be there.
You can also find a highly comprehensible guide of communication in JSF (listing a really extensive list of options) here, in particular if you need to navigate between pages in different folders.
Related
I’m using struts2 + spring3 for my project. Please help me to resolve this problem.
In my app, (a.jsp) relate to --> (aAction.java).
From the main menu, user can access a.jsp. There are so many fields in the a.jsp that user need to key in data. In the middle of the page, user needs to go another page (b.jsp) to add some more details. (b.jsp page is not a popup window) After adding data to b.jsp, user needs to come back to a.jsp. How can I retain a.jsp page data?
Only one action use for both pages (aAction.java).
1) I can keep hidden variables in b.jsp and populate data again in a.jsp. But there are so many
fields in a.jsp. So this way is tedious.
Is there any way to handle this problem with bean scope? Or any other way to do?
There are several ways to do this
use redirectActions in struts.xml. When defining results you can set the type to redirectAction. Then you can redirect to another action and pass params that will be added as parameters to the url
http://struts.apache.org/release/2.1.x/docs/redirect-action-result.html
use localStorage instead of session storage. Limit is 5 MB. Care needs to be taken when using session storage as it can affect the server's performance
if you are using struts, you can make your own type converter for passing any object. Alternatively you could create an string array of the values you want to persist and pass it as a param in struts.xml (see above). Struts has built in type converter for persisting string arrays between pages/actions
you could also save them in cookies and then delete the cookies as soon as the values are not needed as there is a limit on the number of cookies browsers can support
I usually use session storage as a last resort for the reason mentioned above
It's difficult to tell what is being asked here. This question is ambiguous, vague, incomplete, overly broad, or rhetorical and cannot be reasonably answered in its current form. For help clarifying this question so that it can be reopened, visit the help center.
Closed 10 years ago.
It is probably a kind of architectural question, but still it has to have a 'best practice solution' or an accepted standard.
I am talking about some kind of static data that needs to be displayed on site, like catalogue of products, list of menus and menu items, list of breadcrumb blocks etc. This option is available when using any standard CMS, I suppose.
But I would like to use a pure JSF solution for this issue.
So, to get back to the question, my elaborations stem upon the following principles:
Data shouldn't be hardcoded in facelets, hence I use database to hold the values, like in the following db script (MYSQL in my case):
CREATE TABLE CatalogueGroup (
CatalogueGroupName VARCHAR(100) NOT NULL PRIMARY KEY,
URLPath VARCHAR(200) NOT NULL,
ParentGroupName VARCHAR(100) DEFAULT NULL,
FOREIGN KEY (ParentGroupName) REFERENCES CatalogueGroup(CatalogueGroupName) ON UPDATE CASCADE ON DELETE SET NULL
)ENGINE=InnoDB DEFAULT CHARSET=utf8;
I would then like to use the entity class to be held in a #ManagedBean and display it in a view, like
public class CatalogueGroup implements Serializable {
private String catalogueGroupName;
private List<CatalogueGroup> children = new ArrayList<CatalogueGroup>();
private CatalogueGroup parentGroup;
//other stuff of this bean
}
#ManagedBean
#SessionScoped
public class CatalogueBean implements Serializable {
private CatalogueGroup catalogue;//loaded via CatalogueGroupDAO with condition parentGroup == null
//other stuff of this bean
}
//snippet of xhtml view for a two-level catalogue
<ul><h:outputText value="#{catalogueBean.catalogue.catalogueGroupName}" />
<ui:rereat value="#{catalogueBean.catalogue.children}" var="group">
<li><h:outputText value="#{group.catalogueGroupName}" /></li>
</ui:repeat>
</ul>
The abovementioned setup works, but it feels like it is an awkward one.
So, I would like to raise the following open, 'best practice' questions to the jsf community:
What is a proper way of setting up a catalogue bean like this:
A #SessionScope bean that will be loaded once and redisplayed on every view or
A #RequestScoped bean that will access database on every page display.
Is there a way to setup recursive functions in facelet view, or I should limit the catalogue nesting level to, say, 2 or 3.
I would like to display some kind of modified catalogue, exposing more groups to the logged in users, depending on his role (column added in a database table) and display basic catalogue when no user logs in. Additionally, I would like to occasionally insert some new groups in the catalogue and not force users to re-log in, but redisplay proper data at once:
Shall I filter groups in business layer and expose a filtered CatalogueGroup to the bean, or I will load the whole catalogue and limit its children in views with rendered=false;
Is exposure of a whole catalogue in session a proper way to go;
Is it possible to send modification events on adding new database entries to all current CatalogueBean active on server forcing to refresh their properties (CatalogueGroup) or to achieve this functionality I need to use #RequestScoped bean only;
In case using request scoped bean is the only alternative will it be wise to access database to get data so often that rarely change or there is a smarter way of doing things;
When user logs in (and logs out) there is already an instance of session scoped catalogue, how to refresh it: do I need to manually do it in action/action listener or I need to invalidate session or do something more appropriate to the situation.
Very interesting but maybe so open fielded question.
First of all the scope depends on which utility you will give to your catalog. I suggest you to go through #ViewScoped if you want to link the data to a particular view or #SessionScoped if your aim is to implement something like a shopping basket.
For the recursive functions I think you should avoid that kind of practice in pure view (xhtml) layer and use a library like Primefaces or Richfaces which have built-in component for what you want to do. Using them you only have to take care of their logical structure programatically inside your managed backing bean.
Finally, for catalog limitations, I suggest you to load only what you are going to use from the database. In that way you are not overloading neither the server-database or the server-client connections. You can have a #SessionScoped bean which manages current logged user's session and depending on that you can ask the database for some values or others.
Also you have to take care about your catalog, if you are doing a lot of modifications on it during the session, maybe #ViewScoped bean is a better choice, because it will be realoaded each time view is requested. If you use #SessionScoped bean for that you have to manually add each change on it, in order to maintain it updated during the session.
"load the whole catalogue and limit its children in views with rendered=false"
That's a work you don't have to do if you do it the way I say. Conditionally evaluating each of the tree nodes can be a hell if you are managing a complex tree and introduces more logic into the view. Definitely you should avoid that as far as you can.
Even you have already reached a solution, that's my main idea about that.
You can use a cache to store the menus for various user roles. Then you either invalidate the cache when you insert new data in the database (if you insert this from an administration page) or you can set the cache to expire after a certain period (once a day, every few hours, etc.) and you read again the data when the cache expires.
I've been working with ASP.NET(WebForm) for a while, but new to ASP.NET MVC. From many articles I've read, in most cases the reason that the controllers are hard to test is because they are accessing the runtime components: HttpContext (including Request, Response ...). Accessing HttpContext in a controller seems bad.
However, I must access these components somewhere, reading input from Request, sending results back via Response, and using Session to hold a few state variables.
So where is the best place to access these runtime components if we don't access them in a controller?
when you call a model method in your controller, the Request and Response objects are carrying the same value or outputting to the same source. the "page" is what matters there for these objects.
And one more thing, the Request,Session and Response objects may not be directly referenced in your models so you can use System.Web.HttpContext.Current to get the objects. They will function the same as its called from the controller.
And Controllers meant to be as a bridge between views and models, and models should work even if there isn't any Response or Request value in these objects, so I would use these objects' values as usual parameters to model methods instead of referencing them inside the model. It's the right usage of the MVC concept.
If you really must access access these objects from your controller you could always just abstract them and inject a mock instance of them to isolate your testing to just the controller.
In MVC the HttpContext is actually HttpContextBase. It is completely fine to use these classes directly. If you need to later test your controllers you can mock these classes very easily.
http://www.hanselman.com/blog/ASPNETMVCSessionAtMix08TDDAndMvcMockHelpers.aspx
I see nothing wrong with what you want to do.
Accessing HttpContext in a controller seems bad.
No it is not, it just requires you to think about how you will test your action. If you don't test, then you probably don't even have a problem. I recommend you test though.
I have an action that populates the result from the DB. Right now, I see a way of doing it and that is to make the Action ServletRequestAware, set the populated list as a request attribute and show it in jsp.
Since a lot of improvements have been introduced into struts2, is there any other way of doing that? The first thing that comes to my mind is to use displayTag and change the return type of Action to a List, but that does not seem to work.
Thanks for any replies in advance.
You question is unclear, you should read some book about Struts2 to get the general idea.
No need to make the Action ServletRequestAware. The mapping from http parameters to actions fields is automatically done via the Param interceptor (already set in the default configuration). And one of the points of Struts2 is decoupling the action from the http protocol, you should not (typically) do anything related to http in your action.
Tipically, in your action execute() method (or whatever) you'll get the data to display from the DB and set it as one property of your action, so that is accesable from some getter.
Then, in your view page (JSP or whatever) you'll display it. You can use displayTag, but first you'll prefer to display it "manually", to understand what's involved. See for example here http://www.roseindia.net/struts/struts2/struts2controltags/iterator-tag.shtml
For manually displaying a table, also see this example http://www.vaannila.com/struts-2/struts-2-example/struts-2-crud-example-1.html , search for the <table class="userTable> tag.
I have a simple web-site. Almost every action takes int toonId as an argument (toonId does not equate to the user: one user can own multiple toons).
At the moment I provide that value to every view from controller, and every link and submit button sends this value back to the controller.
This works. I am just looking for an easier way to accomplish this (AOP comes to mind).
I use cookies to persist "favorite/default toon", and this works fine (used with ActionAttribute, that takes toonId from cookie and passes is to the toonId argument, if toonId wasn't provided). But I want to support cookie-less sessions as well.
Question: What is an easy way to add ambient variable to the page, without passing it explicitly all over? Such that it would work with cookie-less browsers.
Is Viewstate a way to go (which isn't supposed to be in the MVC)?
Is server-side session a way to go?
This is exactly what session is meant for.
There is no page lifecycle in asp.net mvc, hence no viewstate.
I believe you can automatically pass query string parameters for use cookie-less browsers if you plug in your own implementation of IRouteHandler. I have not tried it though. I found an example of implementing IRouteHandler although it does not show how to implement the query string parameter functionality.
I'm not clear on what 'toonid' represents. If it's 'ambient per user session', then as womp stated, Session state would work well for this. However, if it's somethign that has a larger scope (e.g. a colleciton of toonids that are commonly accessed by all users) then teh Cache would be a better and more scalable strategy.