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).
Related
I have seen many examples where the #Controller annotation is used in web applications build using spring f/w.
Also, I have seen #RestController for creating a web application in spring.
And third what I usually refer to create web application is by specifying spring servlet in web.xml and create controller classes by implementing Controller interface or by extending either AbstractController.
What is the difference in these approaches? Are there any more approaches other than what I have mentioned?
#Controller is typically used for a MVC Controller system and this allows you to return a model to your view from within the controller.
#RestController is typically used for RESTful web-services and this typically will output XML or JSON that you can unmarshal from POJOs with libraries or by overriding the ToString() method of the POJO.
In all instances (unless you are using Spring Boot) you will typically still use a web.xml. I prefer using the annotation approach (#Controller and/or #RestController) as it means less fiddling around with XML files.
I prefer not to use the third method you mentioned as it feels less flexible to me and more complicated.
Apart from above Answer, I would like to add some use cases of #Controller annotation that might be helpful to you.
1) multiple URL patterns can be handled by a single method.
#RequestMapping({"/hello", "/hi", "/greetings"})
2) Controller at the class and method level
#Controller
#RequestMapping("/admin")
public class AdminController {
#RequestMapping("/listUsers")
public ModelAndView listUsers() {
}
#RequestMapping("/saveUser")
public ModelAndView saveUser(User user) {
}
#RequestMapping("/deleteUser")
public ModelAndView deleteUser(User user) {
}
}
Note: If you want to use #Controller instead of #RestController you need to add #ResponseBody annotation like below:
#RequestMapping("admin/getVendorDetails")
public #ResponseBody <Return Type> getVendorDetails(HttpServletRequest request){
...
}
Why can't we autowire the static instance variable in the Spring bean. I know there is another way to achieve this but just want to know why cant we do it in below way.
e.g.
#Autowired
public static Test test;
We can't autowire static fields in spring because the Spring context might not be loaded when the java class loader loads the static values.
In that case the class loader won't properly inject the static fields in the bean and will fail.
Because using static fields encourages the usage of static methods. And static methods are evil. The main purpose of dependency injection is to let the container create objects for you and wire them. Also it makes testing easier.
Once you start to use static methods, you no longer need to create an instance of object and testing is much harder. Also you cannot create several instances of a given class, each with a different dependency being injected (because the field is implicitly shared and creates global state - also evil).
According to OOP concept, it will be bad design if static variables are autowired.
Static variable is not a property of Object, but it is a property of a Class.
Spring auto wiring is done on objects, and that makes the design clean in my opinion.
You can deploy the auto wired bean object as singleton, and achieve the same as defining it static.
By this solution you can autowired static fields in spring.
#Component
public class TestClass {
private static Test test;
#Autowired
public void setTest(Test test) {
TestClass.test = test;
}
}
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.
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.
I'd like to be able to create a base controller in my Spring app that, among other things, determines if a user is a registered user or not. This base controller, following the template design pattern, would contain an abstract protected method that controller subclasses would implement.
The abstract method would have passed to it an instance of User, registered or otherwise. However, I have no idea how I would do this since it seems that by using controllers purely using the #Controller annotation each controller is free to define their request handling method however they like.
Would creating some sort of user service class that is injected into each controller and used to validate a user be one way to get around this? This begs the question (at least for me) how does such a controller get a hold of a HttpServletRequest or the Session object?
Thanks.
Define an abstract BaseController, with no annotations
Define concrete and abstract methods
Call these methods from subclasses (which are annotated with #Controller) whenever needed.
I think the Base Controller is not a good idea if the only code it is to have is for UserAuthentication...instead use Spring security. This is the best option.
Alternatively, you can have methods like this...take a look at the Spring reference..
#Controller("loginController")
public class LoginController {
#RequestMapping(value="/login.do", method=RequestMethod.POST)
public String login(Model model, HttpServletRequest request) {
String userIdFromRequest = (String)request.getParameter("userId");
String password = (String)request.getParameter("password");
boolean verified = ...send userIdFromRequest and password to the user service for
verification...
if (verified){
request.getSession().setAttribute("userId", userIdFromRequest);
}
}
//More Methods
}
Did it help?
-SB
The basic problem is that annotational bootstrapping is not polymorphic. I found this paper useful: http://sanguinecomputing.com/design-pattern-for-hierarchical-controller-organization-with-annotational-configuration-spring-mvc-3/