I am trying to convert a session scoped JSF managed bean to view scoped. However, when I try to access the xhtml page for this bean, then i get the following error:
java.io.NotSerializableException: foo.bar.SomeDaoClass
I have a member of a helper DAO that I use to delegate persistence related tasks within the bean. If I make this DAO class implement Serializable then other UIComponent references start causing the same errors!
The main use case is that I have a link on the click of which I open a jquery lightbox pop-up showing the xhtml page which is backed by a session bean. When the user clicks the submit button on the pop-up form, I remove the session bean programatically. The problem is if the user clicks the close button of the pop-up itself, and clicks on another link pointing to another id, then the same values are shown (being session scoped)!
I would like to use the view scope to preserve values while viewing this form in a pop-up and when the user clicks the close button of the pop-up, the values may be discarded.
I hope you've already resolved this problem, but for other people landing here, who don't want to use session scope and uses view scope as alternative, which force you to use serializable implementation, you can use the transient keyword next to the properties that you don't want to make serializable, that would be very helpful if you want to call a service or dao.
example:
#ManagedBean(name="addressTableBeanExample4")
#ViewScoped
public class ExampleBean4 implements Serializable {
private static final long serialVersionUID = 1L;
// non serialazable class
private transient List<Customer> data = new ArrayList<Customer>();
private Customer selected;
}
Referring to Balusc blog
http://balusc.blogspot.com/2010/06/benefits-and-pitfalls-of-viewscoped.html
"In a nutshell: the #ViewScoped breaks when any UIComponent is bound to the bean using binding attribute"
Related
I have a web site that consists of approximately 30 html thymeleaf templates. I have a home_navigation.html fragment that gets included in all templates as the header. This header defines a main navigational menu with popup submenus. The popup submenus under one of my main menus needs to be generated from my oracle database table.
Normally when passing data from a database into a Thymeleaf template I would put the code in the controller to call the java DAO and return a list of Link objects and then add that list in the controller to the model using .setAttribute. Then in the Thymeleaf template I would iterate through the "${List}" in a "th:each" outputting the "<a href..." for each Link object in the list. That is all fine and dandy.
I also can pass parameters into the fragment. So that isn't the problem BUT...
Since the main navigational menu is added as a header fragment into the beginning of every template then I would have to go into every defined controller and add code that would pull the list of Links and pass it into the template and then pass the list into the fragment from every page. that would be approximately 30 times!!!
How...using Spring Boot and Thymeleaf, does someone feed data into a fragment to populate a menu dynamically from a database that is then added as a header fragment into every page/template on the site?
Is there a way to create a controller for the fragment and somehow have every page call the controller for the fragment before the fragment contents are put into every page?
Thank you.
There are a number of ways to solve this problem depending on whether your menu can change while the user is logged in. If it can change then you can create a base controller class that has a method annotated with #ModelAttribute. All of your controllers would inherit from this base class. This method would obtain the menu items and add them to the model each time a page is requested. A simplistic example of such a class is:
#Component
public abstract class BaseController {
#Autowired
private AlphabetService alphabetService;
#ModelAttribute(name = "alphabet")
public List<String> getAlphabet() {
return alphabetService.getCharacters();
}
}
Your page would access them as normal
th:each="character : ${alphabet}"
You could also access the service directly in the page by doing something like
th:each="character: ${#alphabetService.getCharacters()}"
If the menu items do not change while the user is logged in then you could add #SessionAttributes("alphabet") at the class level to the above example and the service method would be called only once when the first page is displayed and cached in the session for future access.
This question already has an answer here:
#ViewScoped calls #PostConstruct on every postback request
(1 answer)
Closed 6 years ago.
I have a #ViewScope ManagedBean and a #PostConstruct initialisation method. This method is called when a new instance is created, but also on every ajax call. Why is this so?
On an AJAX-call the init-Method is called and executed, but no changes are visible. For example if I change a property in the init-Method, this is only visible on instatiation and not for AJAX-calls. For AJAX-calls the value change is not persistent in the #ViewScoped Bean.
Can anyone tell why this is so? How can I change this?
This is not normal behavior. This will happen if you bind tag handler attributes or the binding attribute of JSF components to a property of a view scoped bean while partial state saving is turned on. This is known as issue 1492 which is fixed in (the upcoming) Mojarra 2.2.
In general, you can recognize tag handlers by the lack of the rendered attribute. E.g. <c:if>, <f:validator>, <ui:include>, etc. If you bind an attribute of such a tag handler to a property of the view scoped bean like follows
<c:if test="#{viewScopedBean.something}"></c:if>
<h:inputText><f:validator binding="#{viewScopedBean.validate}" /></h:inputText>
<ui:include src="#{viewScopedBean.includePage}" />
then the view scoped bean will be recreated everytime the view is to be restored from a partially saved state. This is a chicken-egg issue with the view scope, because in order to get the right view scoped bean, it has to be extracted from the restored view.
This will also happen if you reference a property of a view scoped bean in the binding attribute of a JSF component.
<h:someComponent binding="#{viewScopedBean.someComponent}" />
See also:
Communication in JSF 2.0 - #ViewScoped fails in tag handlers
A WP 7.1 project starts with a Page that host a Panorama control. At some point user click on a ListBox, and this navigates the application to a details page.
In case the debugger is attached, everything stays on the screen as it should. But If I test an application either in emulator, or on the phone without a debugger, approximately in 5-10 seconds after the details page navigation, an application gets deactivated.
No unhanded exception, not closing, but deactivated even is raised. I have placed a message boxes in each of "exit handlers" to know exactly what happens and found out that it is deactivation.
No user input takes place after navigation and before the deactivation.
What may be the reason for such "no interaction" deactivation?
I don't call no "deactivate" requests from code.
Additional info:
Details page is bound to a sample view model that is obtained via MVVM Light ViewModel locator. View model locator gets it from ninject kernel that is a static public property of an App object(Yes, I have made IOC container publicly available via App property. I know it probably is a horrible practice, but I doubt the problem is linked to that). The page initializes just fine and displays all the data from a sample view model class. It almost seems like an app is deactivated due to inactivity, but there is no such thing in WP7 as far as I know.
UPDATE
A deactivation takes place exactly 10 seconds afer I call this line:
((PhoneApplicationFrame)(Application.Current.RootVisual)).Navigate(new Uri("/Views/BookDetailsView.xaml", UriKind.Relative));
from a view model of a main application view. The problem view is a details view, not the main one.
The constructor for BookDetailsView is empty (default):
public partial class BookDetailsView : UserControl
{
public BookDetailsView()
{
InitializeComponent();
}
}
The XAML for the view binds it's datacontext to a property of a mvvm light view model locator:
DataContext="{Binding Source={StaticResource Locator}, Path=BookDetails}"
The Locator resource is decleared in App.xaml and points to ViewModelLocator.cs.
The property that provides datacontext for a problem view is:
public static IBookDetailsViewModel BookDetailsStatic
{
get;
set;
}
/// <summary>
/// Gets the Main property.
/// </summary>
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance",
"CA1822:MarkMembersAsStatic",
Justification = "This non-static member is needed for data binding purposes.")]
public IBookDetailsViewModel BookDetails
{
get
{
return BookDetailsStatic;
}
}
The BookDetailsStatic is initialized from the IoC container call in the ViewModelLocator ctor:
BookDetailsStatic = App.Kernel.Get<IBookDetailsViewModel>();
In a any scenario the call to get an IBookDetailsViewModel returns an instance of a
public class SampleBookDetailsViewModel: IBookDetailsViewModel
which has an empty constructor and a bunch of properties.
SOLVED
My view, that I have been navigating to, was declared as a UserControl, and should have been as PhoneApplicationPage.
Hard to say without knowing what's on the page, but you could be hitting the memory limit.
In general, you can consider the memory limit to be 90mb, but you're better off checking DeviceStatus.ApplicationMemoryUsageLimit and DeviceStatus.ApplicationCurrentMemoryUsage and possibly displaying it on screen every half second or so to debug.
You can also try the profiler, assuming it doesn't affect the repro.
BookDetailsView was decleared as a UserControl.
Navigating to a UserControl deactivates an application in 10 seconds.
Changing the type of a view to PhoneApplicationPage solves the problem.
I have a rich dataTable that's defined inside of an a4j:outputPanel, and that's bound to a session-scoped backing bean that creates the HtmlDataTable. By itself, that part of my code is working fine, and the dataTable looks good.
On another part of the page, there are some basic text links that I'm creating as a4j:commandLinks, and when those are clicked, the dataTable should be re-rendered with new row and column data. The row data's updating fine, but the column data (header text, width, etc.) isn't.
After digging around the code for a bit, it seems that the call to the backing bean for the HtmlDataTable isn't being made during the reRendering of that table, but it is reRendered if the whole page is reloaded; so it seems that it's just the ajax4jsf/reRendering portion that's biting me here.
Is there any way that I can force the reRender process to invalidate the dataTable structure so that it will call the backing bean again for it?
If it means anything, I'm also using Seam; so if there's a solution to be found using it, that'd be helpful, too.
Thanks!
For posterity's sake, I've found the solution: Whenever the a4j request is made to my action listener bean, I have it tell the dataTable-building bean to flush its table. That bean then does a simple myDataTable.getParent().getChildren().remove(myDataTable). This page helped me figure it out: http://www.coderanch.com/t/213312/JSF/java/dynamic-datatable-binding.
In your action just remove the session scoped bean from your contexts.
For example:
<a:commandLink action="#{someBean.perform}" value="Submit" reRender="myTable"/>
and the action:
#Name("someBean")
public class SomeBean {
public void perform() {
//do stuff
Contexts.removeFromAllContexts("myBean");
}
}
Othewrwise if your dataTable is populated with a list then it's probably as easy as just calling the search() or whatever method loads the data.
I've inherited an ASP.NET application built on top of webforms, and the application suffers from having all of its business logic embedded in the codebehind. As a result, this application can't be unit tested.
I want to break out the functionality of every form into an MVC style, but I've found that ASP.NET resists every effort on my part to refactor it. In general, I like to seperate my MVC classes as follows:
public class LoginModel
{
public string Username, Password;
public bool IsAuthenticated;
}
public interface ILoginView
{
event Action UserLoggedIn;
void SetMode(bool isAuthenticated);
}
public class LoginController
{
ILoginView View;
LoginModel Model;
public LoginController(ILoginView view, LoginModel model)
{
this.View = view;
this.Model = model;
// hook onto view events
}
}
Once I've got my classes set up and nicely unit tested, I can implement the ILoginView interface on my usercontrol or page:
public class LoginView : UserControl, ILoginView
{
public LoginView() : base()
{
new LoginController(this); // registers view with the controller
}
}
If this were a winform application, it would work beautifullly. But the ASP.NET lifecycle causes this style to break down.
ASP.NET creates and destroys the view on every page load. Since my Controller is held by the View, the Model is held by the Controller, every postback causes my page to lose its state.
I can remedy the problem above by holding my Controller in the users session, but that introduces a world of problems. In particular, putting Controllers in the session causes memory issues because Models and Controllersaren't reclaimed by garbage collection until the session expires. Navigating from page to page creates dozens of controllers, but the controllers don't dispose of themselves when the user navigates away from a page.
Since a view is destroyed/recreated on every postback, then I have to re-register the view with the controller on every postback. This is harder to do than it sounds, because the state of the Model needs to be copied back to the View on every postback, but simultaneously we don't want to overwrite a users changes to the View which were made in the previous postback. You have no idea what kind of additional nightmare this turns into when dealing with dynamically created or AJAXed controls using this MVC style.
I know I'm overthinking this and there is an easier way to get the results I want, but how do I implement an MVC style properly using webforms?
Is it not easier to re-write this using asp.net mvc?
As it seems you'll have to re-write. Either completely to MVC (and stop using DNN), or to a better WebForms implementation (meaning, separate logic from display and take into account the page life-cycle issues). There's a third option - combining MVC and ASP.NET WebForms, but you should look at it carefully taking into account all the variables in your platform.
Well the nature of the POSTback is dictating your state changes, so you should react on that. Any framework you use would work pretty much the same way, it'll rebuild/bind the state with each request. You should look into savind the state (read data) into your user's session.
ViewState should be used to store all the loaded data in WebForms, so the Controller would be instancied only when the page is created, eliminating the need to store any object in the user session.