The problem that present here is a solution that I am thinking about a particular situation.
Technology Stack: Primefaces, JSF and Spring Framework.
My application
My Web App shows the result of a report in a DataTable of Primefaces. The report has to open in a new tab of the browser. The datable table uses the filters in the datatable header. I have only one view XHTML where the reports it is showed.
My design
#ViewScope
#Controller
public class MBReport implements Serializable {
private transient LazyDataModel<String[]> lazyData;
public void report1(){
lazyData = new...
}
public void report2(){
lazyData = new...
}
public void report3(){
lazyData = new...
}
//setters and getters
}
My problem
When I show the first report no have problem. When I show the second report no have problem. But, when I try to use the filters of the first report the app crash, because it has lost the reference pointer, and it has been replaced by the second report.
I have the idea if I make a different instance object of the Controller with each request, the problem will be solved, but I cannot to do. I tried with the faces scope (viewscope, flowscope, resquestscope) and Spring beans scope (request, session and application).
The fast solution is to make various View files and lazyData field. But that I don’t like so much.
Could you help me with some ideas for my problem?
Related
I have internationalization module and application runs in two different modes. To change the mode, we need to restart the tomcat server. Mode 1 supports two languages and mode 2 supports 5 languages. The languages are stored in a .json file.
Every time the user hits index.html, in the #RequestMapping of this page, I check the application mode. And based on this application mode I read the correct .json file. Extract the list of languages and set that in the model and then I return the page to the client.
Problems with this approach is - every time I hit the index.html file, the application reads the file from disk. which is not only unnecessary but also time consuming and it rings annoying bell to my developer ego.
What I'd like to have instead is, when the application boots up, I know the application mode.
How can get the spring MVC to read the file in the beginning and store this data as long as server is running? Is it even possible?
If yes, can you let me know what parts of Spring MVC do I need to look into?
I read about HandlerInterceptor and #ModelAttribute but it merely states how can I insert the data in each request. However, what I really want to know is how the persist the data read from the file once.
One of the approaches could be tohave a bean, which impements InitializingBean and loads the file in 'afterPropertiesSet' method. It would also have a method to return the list of languages and it could be wired into all other bean which need it.
You could also do it in 'HandlerInterceptor', just have it implement InitializingBean and store the list in the class variable.
e.g.
public MyInterceptor extends HandlerInterceptorAdaptor implements InitializingBean {
private List<String> languageList;
#Override
void postHandle(HttpServletRequest request,
HttpServletResponse response,
Object handler,
ModelAndView modelAndView)
throws Exception {
//set list in the model
}
#Override
public void afterPropetiesSet() {
languageList=...; //read file
}
}
I've been struggling with this issue as I'm new to Struts2 development, and just started using this naming Convention Plugin recently.
I'm trying to create a simple webapp which at first will only consist in two pages:
Login page (login.jsp)
Home page (home.jsp)
First a login page is shown to the user, and if the correct username and password are provided, they log in and get redirected to the home page.
I've successfully managed to create my small webapp, writing down a custom login interceptor and everything's OK and working as expected. I'm able to redirect the user to the login page if he/she tries to call the HomeAction( which results in home.jspif you previously logged in) directly like http://myserver/homeAction.
Problem comes when I try to access JSPs directly like this:
http://myserver/home
As I'm using this Convention plugin, Struts fetches my home.jspplugin and displays it. This is not the behaviour I expected, as home.jspshould be shown only as a loginAction successful result.
Things I tried to solve this issue
Well, as far as I googled, putting my JSPs inside /WEB-INF/directory should prevent them to be accessed, but it doesn't, as all my JSPs are in /WEB-INF/content/.
Another thing I tried was blocking access to any JSPresource (blocking *.JSP requests). This does the trick as long as you try to access myserver/home.jsp , but fails (as expected) when accessing myserver/home.
EDIT: There's another question in stackoverflow about this issue but I can't understand the answer:
Struts 2 Convention Plugin and JSP files under WEB-INF
INFORMATION UPDATE: I've found that Struts2 convention plugin uses something called "actionless results" so you can access your JSPs inside your WEB-INF/contentdirectory by invoking the JSP without it's extension and it will deal with it as a dummy action which returns that JSP on success. This is an example to illustrate what I'm trying to explain:
If I have home.jsp in my WEB-INF/contentdirectory and call http://myserver/home, Struts2 will "trigger" an action whose result is going to be home.jsp. The solution for the problem then is going to be disabling this "actionless" results.
I'll keep updating the question as I head towards the solution if nobody provides an answer.
Here how d'you want to disable this feature.
Create a dummy bean:
package com.struts.handler;
import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.Result;
import com.opensymphony.xwork2.UnknownHandler;
import com.opensymphony.xwork2.XWorkException;
import com.opensymphony.xwork2.config.entities.ActionConfig;
/**
* Created by Roman C on 22.03.2015.
*/
public class MyUnknownHandler implements UnknownHandler {
#Override
public ActionConfig handleUnknownAction(String namespace, String actionName) throws XWorkException {
return null;
}
#Override
public Result handleUnknownResult(ActionContext actionContext, String actionName, ActionConfig actionConfig, String resultCode) throws XWorkException {
return null;
}
#Override
public Object handleUnknownActionMethod(Object action, String methodName) throws NoSuchMethodException {
return null;
}
}
Then configure it in the struts.xml:
<bean type="com.opensymphony.xwork2.UnknownHandler" name="handler" class="com.struts.handler.MyUnknownHandler"/>
<unknown-handler-stack>
<unknown-handler-ref name="handler"/>
</unknown-handler-stack>
Explained here:
The convention plugin along with configuration it creates mentioned above also put an unknown handler which should handle URLs for which a configuration is not exist (i.e. not created by the convention). This is the source of the problem.
Now putting your own handler will disable convention's one. Thus it will no longer handle results by convention.
I am writing a spring mvc app with a use case of custom messages (labels) per each client. Each request will have a unique key in the path like:
http://somehost/something/A1B2C3D4/page
http://somehost/something/H7CD8E31/page
Based off the key I will load custom messages from a database.
I found an article that uses custom database messages for the whole app here:
Custom Database messages
I modified this approach a bit and read the request using the following code:
private String getIdFromRequest() {
ServletRequestAttributes attr = (ServletRequestAttributes) RequestContextHolder.currentRequestAttributes();
HttpServletRequest req = attr.getRequest();
String id=null;
try {
id = ((String) req.getServletPath()).split("/")[1];
} catch(Exception e) {
System.out.println("Request did not have key");
}
return id;
}
I then call this message inside resolveCode of my class that extends ReloadableResourceBundleMessageSource.
If a page has 20 messages then this block of code is run 20 times per page. My question is where or how does spring read the messages from the view template? When rendering a view, it resolves the view to a file, then it must loop over the messages calling resolveCode on each one. I wanted to call my getIdFromRequest method once per page by extended the class where the looping takes place. I was looking through the spring source code but I can not find what I am looking for yet.
Can anyone point me in the right direction? Also if there is a better way to solve my issue I would appreciate some direction on that as well.
You did not spoke of thymeleaf in your question, but as it is in the tags, I assume you are using it.
If it is the case, as thymeleaf is a template library, all is done at view rendering. I think that the relevant class is not a spring class but a thymeleaf one.
I advice you to look in org.thymeleaf.spring3.view which is the view you are using in your application. If you want to use a specialized subclass, you should probaly first subclass the ViewResolver from same package.
If you do not use thymeleaf, the general workflow is the same : you have a ViewResolver declared in spring context. The ViewResolver instantiate a View and all the actual building of the response occurs in the View.
I'd like to develop a vaadin application with spring. A user should be able to login and see uer-specific pages. I he comes to the site from a different browser window, it would be handy if the user is still logged in, so preserves the session.
Now I wonder which scope to use for this purpose? Vaadin and Spring offer a #Scope("session"), #Scope("ui") and a #Scope("prototype"). Should I just place all of my *View and *Presenter classes in the session scope?
Or would it be better to have the view annoted with prototype, so that each time a pages is changed the page is recreated with updated data?
In this case, should then the presenters be still session scope, or also prototye?
Or should I at all use the ui scope that's provided by vaadin4spring boot addon? This would then create a new "uiSession" for every new tab.
#Scope("session")
class MyPresenter {
//each view should be wired to a presenter
#Autowired
private MyView view;
}
#Scope("prototype") //"session", "ui"?
class MyView extends VerticalLayout {
#PostConstruct
public void init() {
addComponent(new Label("time is: " + new Date()));
}
}
vaadin stores (large amounts of) state in the session. state is pretty much anything, that is visible to the client in the browser. the ui scope is what you should use, if any component is involved. even if ui and session seem the same, you should stick to ui to prevent raceconditions and worse against the vaadin code.
in your example above, view is definetly ui, because it is a component. this makes the presenter ui also as it holds reference to an ui scoped component and will for sure tap into events from it or read data etc.
I have a dynamic Facelets page that needs to show information from database when the page loads. At this point in the flow, there have not been any form submissions. Every JSF example I can find only shows a form submission with dynamic results on the next page.
Every call I make to our database is currently takes place after an action has been triggered by a form submission. Where should this code go if there hasn't been a form submission, and how do I trigger it? A code snippet would really help me out!
You should be able to do your initialization work in the constructor (or lazily in one of your accessors) of your managed bean.
If you're using Spring integration (see here also), it's easy.
In your backing bean, simply use something like:
public class BackingBean implements InitializingBean
{
public void afterPropertiesSet()
{
loadInitialData();
}
}
If you're not integrating with Spring there are two options:
Load the initial data in the class constructor;
In your faces-config.xml, you can set properties to be injected. Properties are guaranteed to be set in the order they're specified in the config file. So, just create a dummy property and then within that method load up your default data. i.e. create a method public void setLoaded(boolean loaded) { loadInitialData(); }, and in your faces-config.xml have 'loaded' being set as a property on that backing bean.
Hope this is all clear!
You write (with my emphasis added):
Every call I make to our database is currently takes place after an action
has been triggered by a form submission. Where should this code go
if there hasn't been a form submission, and how do I trigger it? A
code snippet would really help me out!
It sounds to me that you want to retrieve information from the database prior to form submission.
It seems to me that you want to make an Ajax call to query the database. The Ajax call can fire on a different event than the form submisson event. This will probably entail using Javascript rather than the Faces framework.