I need to store some data into the user session. Normally I would use getSessionMap().put() to solve this. My problem is, that I need to do this in the sessionCreated()-void of my sessionListener, but at this moment the FacesContext is still null. So the code below generates a NullPointerException.
#Override
public void sessionCreated(HttpSessionEvent arg0) {
FacesContext.getCurrentInstance().getExternalContext().getSessionMap().put("data", "something");
}
Is there another way to store data into the session or can I initialize an instance of FacesContext manually? Unfortunately I don't know much about the jsf lifecycle.
Thanks for any help!
You seem to have completely missed the fact that JSF is merely one big abstract layer over the "plain" Servlet API and that ExternalContext (please take all time to carefully read its javadoc, including method descriptions) merely delegates to classes/methods available in "plain" Servlet API.
In your particular case, when you use JSF on top of Servlet API (instead of Portlet API), then the ExternalContext#getSessionMap() is merely a facade of HttpSession#setAttribute()/#getAttribute(). And guess what, HttpSession is in your HttpSessionListener readily available by the HttpSessionEvent argument!
#Override
public void sessionCreated(HttpSessionEvent event) {
event.getSession().setAttribute("data", "something");
}
This is then available by getSessionMap().get("data"), or by #ManagedProperty("#{data}") in any JSF backing bean, or just by #{data} in EL in a JSF page.
Related
I'm using spring data rest with #RepositoryRestResource where all the verbs are automatically handled for all the entities in the system.
There is no controller necessary for my project.
But I do want to perform certain action before the GET call is made to an entity. What is the best way to do this without writing a custom controller?
There are event handlers I can write in Spring Data Rest like #HandleAfterDelete but there are not handlers for GET.
I'm afraid there is currently no solution which would provide this out of the framework itself. However, there is a pull request which was discussed but not yet implemented as there are still open questions with regard to the universality of findBy* methods.
In case you do not need a that general solution the yet suggested HandlerInterceptor is the way to go…
public class YourInterceptor extends HandlerInterceptorAdapter {
#Override
public boolean preHandle(final HttpServletRequest request, final HttpServletResponse response, final Object handler) throws Exception {
// decide on request.getMethod() what to do next
}
}
I am no sure if my codes is thread safe,anyone can help?
#Aspect
public class MyAspect {
#Autowired
private HttpSession session;
#Before("...")
private void myMethod() {
seesion.getId();
}
}
Because MyAspect's scope is default(singleton),so many request exsits at same time and also many session.OK,Which session I get in my code?Is it thread safe?Or it's a wrong code,if it's wrong,how can I do?
Thanks!
Right, it's OK.
Your MyAspect should be registered as bean anyway.
It doesn't matter is it AOP Aspect or not: the dependency injection infrastructure the same.
Now about HttpSession.
This object isn't registered as bean, but for him Spring provide a trick - WebApplicationContextUtils.SessionObjectFactory. This object is registered as
beanFactory.registerResolvableDependency(HttpSession.class, new SessionObjectFactory());
And when the injection works it wraps SessionObjectFactory with Proxy to invoke real methods on demand from ThreadLocal<RequestAttributes> variable. That mean that each call of your MyAspect.myMethod does the stuff for concrete HttpSession, if your current Thread is a Servlet Thread, of course.
So, the answer to your question: yes, it is thread safe.
I have a lot of Controllers that are extends one base Controller which has a static contructor with ResourceBundle generation:
static {
resources = ResourceBundle.getBundle("com.resource.Resources");
}
I need it because app's logic based on locale, not only views.
In addition I have a CookieLocaleResolver that resolves the current locale from the cookie.
The problem is that base controller's static constructor code executes before the CookieLocaleResolver's resolveLocale method so I am always receive a system's default locale at ResourceBundle and not the current one.
How can I solve it? Thank you
That's because the static block is executed at the class initialization time. You need to load the ResourceBundle when the controller is called. I would suggest you here to define your controller as a prototype and use InitializingBean to load the ResourceBundle.
public class MyController implements InitializingBean {
private ResourceBundle resources;
public void afterPropertiesSet() {
resources = ResourceBundle.getBundle("com.resource.Resources");
}
}
A better way would be to use the ResourceBundleMessageSource and not use the ResourceBundle directly. If you can, that would be much easier since you don't have to manage the ResourceBundle directly.
I hope that will help you.
[Edit]
The Spring MessageSource provides methods to resolve messages with parameters. If you define a MessageSource in your application, you will be also able to access the same messages in the view (JSP page for instance). At last, from the design, that is better if the controller doesn't have a direct reference on the resource bundle, this way your labels/messages are managed in a single place (in your Spring config when you declare the MessageSource).
I am using Spring 3 AOP, and I have an aspect that requires access to the HttpServletRequest. It looks something like this:
#Aspect
public class MyAspect {
#Autowired
private HttpServletRequest httpServletRequest;
public void init() {
// Do something once...
}
#Before("my pointcut here...")
private void myMethod() {
// I need the httpServletRequest...
}
#After("my pointcut here...")
private void myOtherMethod() {
// I need the httpServletRequest...
}
}
And is configured like this:
<bean id="myAspect" class="com.some.package.MyAspect" init-method="init" />
Is the init method only called once per IoC container, even though this is an aspect, and is the httpServletRequest thread safe? If it is not, what is the best way to get at it during execution of the advice and have it be thread safe? If at all possible I prefer not to use a thread local.
Is the init method only called once per IoC container
It is called once per every bean instance. If bean has a singleton scope (which is the default case for aspects as well), it will only be called once. However you won't have access to the httpServletRequest inside init() method - there is no request yet!
is the httpServletRequest thread safe
It is not but don't worry. This is actually much more complex than it looks like. You are injecting HTTP servlet request (and obviously there can be several requests available at the same time) into a singleton object. Which one is injected? None (all?) of them! Spring creates some sophisticated proxy (called scoped proxy) and every time you access methods of injected httpServletRequest it delegates them to current (to thread) request. This way you can safely run your aspects in several threads - each will operate on a different physical request.
This whole behaviour is described in great details in 4.5.4.5 Scoped beans as dependencies:
[...] If you want to inject (for example) an HTTP request scoped bean into another bean, you must inject an AOP proxy in place of the scoped bean. That is, you need to inject a proxy object that exposes the same public interface as the scoped object but that can also retrieve the real, target object from the relevant scope (for example, an HTTP request) and delegate method calls onto the real object.
About ThreadLocal:
I prefer not to use a thread local.
Fortunately - Spring is using one for you. If you understand how ThreadLocal works - Spring puts current request into a thread local and delegates to thread-local instance when you access httpServletRequest proxy.
I am writing Spring 3.1.0 MVC based application. The problem is: i want to put some objects in a singleton object (current HttpServletRequest and HttpSevletResponse) to use them in other objects(Spring Controllers). But couldn't do so. I tried to extend DispatcherServlet, overriding both doService and doDispatch. Also tried to implement own HandlerInterceptor. No result.
Where can I initialize my singleton objects? And where is Spring Frameworks's entry point and destroy point (i.e. like init() and destroy() methods or lifecycle)?
The current HttpServletRequest and HttpServletResponse are available as method arguments to your controller methods:
#RequestMapping("/foo")
public String foo(HttpServletRequest request) {
}
I believe you can also #Inject them in your controller. A proxy will be injected, and each time you refer to them the current ones will be used. (I'm not 100% certain about this one)
A third option is to use the RequestContextHolder container, and get everything from there.