In Struts2 we have the Preparable Interface that can be implemented on our Action Class in order to load some services or any data we need.
My questions is if we have something like this in Struts1?
Related
I am working on a spring base web application where, we have a few RestControllers and some Request DTO classes. Request DTO contains a token field which needs some validation. So I used spring validators to validate that. After validation, we want to send that field to an external system using another REST API (Just for some kind of analytics logging). The same field is repeated in multiple DTO objects and their controllers. So, I am easily able to define annotations for validators and reuse them across the DTOs. But I am not sure how to process that field after validation succeeds (i.e. call analytics API to consume that field post validation), without mixing it with the core logic of controllers.
Approaches I could think of:
Implement a filter/interceptor and process the field there. But then
there is a limitation that request body can be read only once so I
need to use some alternate ways by creating request wrappers.
Repeat the logic in every controller and it is very error prone as for
every new controller we need to remember to write that code.
But non of these approaches look cleaner. Can someone recommend a better way to achieve that?
Thanks in advance.
You can create a BaseController and implement the method there. Extend this BaseController wherever you need this logging service. Like below.
BaseController.java
class BaseController {
protected void remoteLogging(String name,String token) {
//Calling the remote log services}
}
AppController.java
#Controller
#RequestMapping("register")
public class LeaseController extends BaseController {
#PostMapping("new")
public String new(#Valid #ModelAttribute("registration") Registration registration,BindingResult result){
if(rest.hasErrors(){
remoteLogging("name","token");
}
}
The way to use a Validator interface for Spring #RestController based is to create a validator custom class, implement Validator interface. In the controller class call InitBinder to register the validator class. Then when the REST req comes, the validator for that class is called. This still has a problem for me. Say I have a PersonValidator class that does one type of validation for POST and another type for PUT. Since both these handlers exist in the same REST controller class, how can I run different validations?
Say in the same rest controller class, i want to use PostPersonValidator for POST and PutPersonValidator for PUT. I do not know how to do it.
Just follow this article: http://howtodoinjava.com/2015/02/12/spring-mvc-custom-validator-example/
You basically have to create two separate validators - just as you said (one for POST, one for PUT). Then just call them inside your proper POST/PUT handling methods. Should be pretty straightforward if you follow the linked example.
I usually add objects in my jsp requestScopes using Controllers.
For example, if I need to list categories in "localhost/products/viewall", I simply change my ProductsController adding something like
#RequestMapping("/products/viewall")
public void viewCategories(Model model) {
List<Category> categories = service.findAllCategories();
model.addAttribute("categories", categories);
}
so, this method adds a list of categories to my requestScope.
I need to do the same, but for all the pages of the website (since the variable I need will be used in the layout of the site).
How can I add something to all the pages requestScopes with Spring?
I think you have at least two possible options for this:
Using an MVC Interceptor. With an interceptor you can perform common operations for all requests. You can extend HandlerInterceptorAdapter and add common model data in postHandle
Using the #ModelAttribute annotation within an Controller. You can use this to add common data for all request mappings within a controller. You can also use an #ControllerAdvice (with #ModelAttribute annotated methods inside) if you want provide model data to all controllers. The section Using #ModelAttribute on a method should provide some additional information for this.
With Spring, how can i retrieve the following Controller attributes in the view?
Controller name
Controller's #RequestMapping URI
Action method name
Action method's #RequestMapping URI
One approach which i have tried is by creating a subclass of HandlerInterceptorAdapter and overriding postHandle. I register my subclass as an mvc:interceptor for a list of given paths - which is clunky to maintain but was the only way to avoid my interceptor being called for ResourceHandler requests (which i don't want). In my postHandle i can easily add the 2 name attributes, but not the URIs...
Parsing from the HttpRequest object requires constraints on all Controller RequestMappings. I.e. i must always map /Controller/Action or equiv scheme. Quite limiting.
Creating an ApplicationContext and querying that with the requestURI is too long-winded.
I am thinking about dropping the HandlerInterceptorAdapter and instead defining a BaseController for all my controllers to extend.
I wanted to ask before i do this, is there a better approach?
You haven't stated why you need to do this (it sometimes helps to include your motivation, as others can suggest alternative approaches).
But I'm guessing that the Spring 3.1 features loosely termed "end point documentation" may do what you are asking... See RequestMappingHandlerMapping in the Spring documentation which doesn't provide a lot of detail, so this example project is the best place to see it in action:
Spring MVC 3.1 Demo App
example controller
example JSP page
Is there a nice way to have Spring's #Controller classes to call a specific method once per request?
Right now I'm using a method annotated with #InitBinder for this purpose, but this is suboptimal as #InitBinder methods get called several times per request. I just want to do some initialization / update stuff to use in my controllers.
What I'm looking for is something like Rails' before_filter, but as far as I can tell there's no functionality like that in Spring.
Sounds like you need a request-scoped controller bean. Spring will create a new instance of the controller for each request, and will initialize the bean each time using the standard mechanisms like #PostConstruct.