How to extend the lifetime of a bean? - spring

I need some JSF 2.1.29 advice. I have a bean:
public class PlayerCardBean{
private Integer playerId;
//GET, SET, Other fileds and methods
}
The facelet playerCard.xhtml for the bean contains <a> tag for redirecting to another page:
<a href="javascript://"
onclick="openPage('#{request.contextPath}/panels/playerExternalTransactionList.html?playerId=#{playerCardBean.playerId}');">
<h:outputText value="#msgs['playerCard.externalTransactionList.all']}" />
</a>
I need this bean stay alived when the user is on the playerCard.xhtml as well as we're redirecting from the playerCard.xhtml to by the link within the <a> tag.
The view scope is smaller. The bean is going to be destroyed after redirecting.
How can I keep that bean alive when we're redirecting between those two views? By the <a> tag and probably by the "back"-button in a browser.
I think that storing the fields within a session is not a good idea because they are not a true-session attributes.

You can use the #ConversationScope. This scope is started and ended programmatically.
http://www.byteslounge.com/tutorials/java-ee-cdi-conversationscoped-example

I can think of the following two solutions:
Use the conversation scope. It requires annotating your bean with the #ConversationScoped annotation and you will need to manage (begin and end) the conversation programatically. (This answer contains some useful sample code.)
Use the Flash.

There is no perfect solution in JSF 2.1 but you can create your own scope which will be good replacement for conversation scope.
More details:
https://blog.oio.de/2012/07/24/jsf-2-custom-scopes-without-3rd-party-libraries/

Related

Spring web app controller field scope

I am experiencing some conceptional difficulty with the scope of some beans referenced in controllers. I have checked a lot of related questions in file and still not sure. Could someone please help me clarify it?
I am numbering the questions or statements as follows to make helper easier to address my problems.
Per my understanding from the the Spring doc, in spring web application,
1) for any controller, annotated with a #Controller, if there is a private field bean, with default bean scope, this field bean will be accessed as the singleton thus susceptible to thread issue;
2) If the field bean is marked as scope=""prototype, this field bean, within this controller, will still behave like a singleton, thus being not-thread safe.
3) To make such a field bean thread safe, we have to make the bean scoped with request or session right?
The following is a simplified example related to this question:
#Controller public Class ControllerA
#Autowired private DefinedBean db;
#RequestMapping("/testPath") public ModelAndView getPathPage(){
this.db.setTitle("abc");
this.db.readReportWithTitle();
....
return new ModelAndView();
}
So in this example,
4) if the DefinedBean is defined through xml configuration with or without explicit scope of prototype, this DefinedBean will have synchronization issue, right?
5) To ensure this DefinedBean to be thread safe, we have to define it explicitly with request or Session.
On the other hand,
6) if we mark the controller itself with a scope of prototype explicitly, will it get rid of the non-thread safe issue with the DefinedBean field? My thought is no, this won't.
7) To make the field thread safe, if we are going to control at the controller level, we need to mark the controller with Scope="Request" as well, right?
Your comments are welcome and appreciated. If you can comment with "Correct" Or "Incorrect" or elaborate further to those numbered (1~7) statements, Myself and possible those who come later will appreciate more.
I think you want to leave the controller be a singleton.
Here is the spring documentation that explains how to bind beans having different scopes.
This is how you would want to define the wired bean:
<bean id="db" class="DefinedBean" scope="request">
<aop:scoped-proxy/>
</bean>
I have looked up to see how the same can be done with annotations only and I have found this.
Basically, you annotate DefinedBean with :
#Scope(value = "session", proxyMode = ScopedProxyMode.INTERFACES)

Deleting from JSF Datatable on a Request Scope Bean

I have a page with a dataTable, which is populated based on the query parameters (e.g., username and pagenum). Each entry in the table has a delete commandButton
When the pagenum != 0 and we click delete, the list of records to display is generated during the "apply" phase. During this phase the view parameters have not been set, so the list of records is empty so nothing get's deleted (our delete method doesn't get called)
To work around this I've added a #PostConstruct method that retrieves the query parameters from the Servlet request and sets the values in the bean, so they are available when we get the list of away records, which allows my delete method to be called.
I'm certain that JSF has a better way of handling this scenario and the #PostConstruct work around is a hack.
What is the correct way to implement this scenario, without resorting to a View or Session scoped bean?
Surely there must be a way to just POST the form and delete the appropriate record without having to waste time regenerating the list of records.
What is the correct way to implement this scenario, without resorting to a View or Session scoped bean? Surely there must be a way to just POST the form and delete the appropriate record without having to waste time regenerating the list of records
Sorry, there's no way. At least not when using a standard <h:commandButton> inside a standard <h:dataTable>. This is the consequence of the stateful nature of JSF. JSF just wants to ensure that the view is exactly the same during processing the postback as it was during generating the HTML output.
This is part of JSF's safeguard against tampered requests wherein the enduser/hacker can manipulate the request parameters in such way that it could do hazardful things, e.g. changing the ID of entry to delete, or bypassing the check on rendered attribute, etc. All those things on which you would/should do additional pre-validation anyway if JSF didn't do that for you and are easily overlooked by starters (they would then blame JSF for being insecure instead of themselves). See also Why JSF saves the state of UI components on server? and commandButton/commandLink/ajax action/listener method not invoked or input value not updated.
In case of <h:commandButton> inside <h:dataTable>, JSF simply needs to have the data model available during the apply request values phase, so that it can iterate over the <h:dataTable> in the component tree in order to find the pressed button and queue the action event. If there's no datamodel, then it can't find the pressed button and the action event won't be queued. Normally, this is to be solved by placing the managed bean in the JSF view scope. See also How to choose the right bean scope?
In case of request scoped beans, the <f:viewParam> is indeed not the right tool for the job of preserving the data model before apply request values phase takes place. You need to do the job in a #PostConstruct annotated method instead. The request parameters can in case of JSF managed beans be injected via #ManagedProperty. See also ViewParam vs #ManagedProperty(value = "#{param.id}"). In case of CDI or Spring managed beans, there's no standard annotation available to inject a HTTP request parameter as a bean property. For CDI, the JSF utility library OmniFaces has a #Param for the very purpose. See also OmniFaces #Param showcase. For Spring, you'd need to homegrow it yourself. I, as non-Spring-user have however no idea how to do that. Google also doesn't seem to reveal much.
Alternatively, you can also just put the bean in the view scope by #ViewScoped. It'll then live as long as you postback to the same view. JSF 2.2 has a CDI compatible annotation for that in javax.faces.view package. The one in javax.faces.bean package is the old JSF 2.0/2.1 annotation for #ManagedBean. Spring has no annotation out the box for this as that would otherwise put a dependency on JSF API. You'd need to homegrow it yourself. Google shows several examples.
What is the correct way to implement this scenario
Before executing the any logic on the backing bean, JSF always have to rebuild the view in order to get information about what to execute. For displaying and updating purpose, the best (and correct) solution is certainly the #ViewScoped.
without resorting to a View or Session scoped bean?
If you insist on using #RequestScoped, I'd say there're no correct ways but work-arounds or hacks. One way is to initialise the list in a #PostConstruct method like you've mentioned. Another way may be to use a JavaScript function for the onclick attribute of your delete button. The JS function, for example, will make a call to the server using a URL to request a delete. Or else, you can also use PrimeFace's RemoteCommand for the JS function.

use spring bean in JSP

i have bean that contain method [void return] and want access to this bean in JSP.
public class A {
public void run() {}
}
add below code to spring config file.
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="exposeContextBeansAsAttributes" value="true"/>
</bean>
<bean id="a" class="com.example.A"
>
</bean>
now in my JSP page :
${a.run}
but this solution not work.please help me for access spring bean on JSP page.
Inject the bean into your controller and expose it as part of the model.
But why do you need to call run from the JSP?
JSP EL expects to follow JavaBean naming conventions; this example won't work the way you expect. The easiest option is to rename the method, or provide an additional method, that follows the JavaBean naming convention and calls run.
Edit to reply to comment.
If you need to call a method from a link, you have two (reasonable) options: link to a controller action that calls the injected service, or make an Ajax call to a controller method that calls the injected service.
There's still zero reason to be making the service call directly from the view layer (the JSP).
You cannot call a method with ${a.run} you need to do #{a.run}.
# Dave Newton's comment : "There's still zero reason to be making the service call directly from the view layer".
Consider a scenario, where you want to develop a custom tag (say a dropdown which fetches values from a service class based upon the tag's attribute value, in your core web project) . and you provide the TAG implementation in a .tag file.
Keeping the service call in the .tag file seems preferable than to update the model in every controller, called prior to render the view which uses the tag. What do you suggest, Using an onload AJAX call in .tag file to fetch the dorpdown content?
Have you tried this?
${a.run()}
I haven't used org.springframework.web.servlet.view.InternalResourceViewResolver (use it's superclass instead), but this works if your controller injects a Java object profile which has toJson() method implemented. Don't see why the same syntax wouldn't work as long as a is accessible to the JSP and implements run().
<script>
$(function() {
var profileJson = ${profile.toJson()};
....
})
</script>
This is how is pre-load my page with initial content and save a trip to the back-end on page load.
You could write a scriptlet for this something like
<%
ApplicationContext ctx = RequestContextUtils.getWebApplicationContext(request);
A a = (A) ctx.getBean("yourBeanName");
%>
or use WebApplicationContextUtils if the requests are routed through DispatcherServlet.
You should look into Spring MVC . This would suit you more.

spring mvc form handling without using spring tag

Recently, I have been researching a new framework for the purpose of building a web-application. To this end, I wanted to try out Spring MVC. Of the many parameters for evaluating a framework, one is that I don't want to be bound to the tag libs associated with the framework to make use of the HTTP request parameter -> Java bean translation. The Spring MVC documentation repeatedly mentions that it is possible to do view related things with only JSTL and no Spring tags, however, I haven't found a way to get the Request-to-Bean translation feature [SimpleFormController] to work without Spring tags.
As of now, the only way seems to extract the request parameters one by one and set to my bean. Is there any way to perform this translation w/o using framework dependent tags?
I appreciate your inputs!
I use Spring Web MVC without Velocity templates (non-JSP templating). To answer your question, you need to understand how Spring performs data binding. Basically, it's all in the name you give your input elements. E.g
<input name="properytOne" value="1" type="hidden">
<input name="properytTwo" value="2" type="hidden">
<input name="rich.property3" value="3" type="hidden">
will bind values to an object like this
class CommandOne {
private String propertyOne;
private String popertyTwo;
private CommandTwo rich;
// Getters and setters
}
class CommandTwo {
private String propertyThree;
// Getters and setters
}
You also have to be sure to instantiate your command object, but that will be handled in your SimpleFormController.
Spring tags are completely optional.
Read chapter 15, 16, and 17 of the Spring Reference Document You can use annotations to retrieve request parameters with your controller (see section 15.3).
As per my understanding, what you are trying to achieve is Binding your form to your Bean Class, which is very nicely implemented in JSF. JSF works on component architecture and very easy to start with, plus it has many component builers available such as primefaces, omnifaces, icefaces, openfaces, etc. Reusability of self-designed components can help you a lot in specific projects. Try giving a chance to JSF. Thanks, hope this was helpful.

Get Request and Session Parameters and Attributes from JSF pages

I'm using JSF with facelets and I need to get the request and session parameters inside the JSF page. In JSP pages I got this parameter like that: "${requestScope.paramName}" or "${sessionScope.paramName}". But now after using JSF there are only beans and you can't get any value except bean attributes.
NOTE: The session attributes what I need is auto filled using acegi security so I can't get any access to them.
So what to do now?
You can get a request parameter id using the expression:
<h:outputText value="#{param['id']}" />
param—An immutable Map of the request parameters for this request, keyed by
parameter name. Only the first value for each parameter name is included.
sessionScope—A Map of the session attributes for this request, keyed by
attribute name.
Section 5.3.1.2 of the JSF 1.0 specification defines the objects that must be resolved by the variable resolver.
You can also use a bean (request scoped is suggested) and directly access the context by way of the FacesContext.
You can get the HttpServletRequest and HttpServletResposne objects by using the following code:
HttpServletRequest req = (HttpServletRequest)FacesContext.getCurrentInstance().getExternalContext().getRequest();
HttpServletResponse res = (HttpServletResponse)FacesContext.getCurrentInstance().getExternalContext().getResponse();
After this, you can access individual parameters via getParameter(paramName) or access the full map via getParameterMap() req object
The reason I suggest a request scoped bean is that you can use these during initialization (worst case scenario being the constructor. Most frameworks give you some place to do code at bean initialization time) and they will be done as your request comes in.
It is, however, a bit of a hack. ;) You may want to look into seeing if there is a JSF Acegi module that will allow you to get access to the variables you need.
You can either use
<h:outputText value="#{param['id']}" /> or
<h:outputText value="#{request.getParameter('id')}" />
However if you want to pass the parameters to your backing beans, using f:viewParam is probably what you want. "A view parameter is a mapping between a query string parameter and a model value."
<f:viewParam name="id" value="#{blog.entryId}"/>
This will set the id param of the GET parameter to the blog bean's entryId field. See http://java.dzone.com/articles/bookmarkability-jsf-2 for the details.
You can like this:
#{requestScope["paramName"]} ,#{sessionScope["paramName"]}
Because requestScope or sessionScope is a Map object.
You can also use a tool like OcpSoft's PrettyFaces to inject dynamic parameter values directly into JSF Beans.
Assuming that you already put your object as attribute on the session map of the current instance of the FacesContext from your managed-bean, you can get it from the JSF page by :
<h:outputText value="#{sessionScope['yourObject'] }" />
If your object has a property, get it by:
<h:ouputText value="#{sessionScope['yourObject'].anyProperty }" />
Are you sure you can't get access to request / session scope variables from a JSF page?
This is what I'm doing in our login page, using Spring Security:
<h:outputText
rendered="#{param.loginFailed == 1 and SPRING_SECURITY_LAST_EXCEPTION != null}">
<span class="msg-error">#{SPRING_SECURITY_LAST_EXCEPTION.message}</span>
</h:outputText>
In the bean you can use session.getAttribute("attributeName");

Resources