Spring Mvc Request forwarding - java

#RequestMapping("/modify")
public String modifyAd(AdDto adDto, Model model){
if (adService.modifyAd(adDto)){
adDto.setTitle("");
model.addAttribute(PageCodeEnum.KEY,PageCodeEnum.MODIFY_SUCCESS);
}else {
model.addAttribute(PageCodeEnum.KEY,PageCodeEnum.MODEFY_FAILED);
}
return "forward:search";
}
The adDto.title I got from jsp is '芒果冰淇淋11',
I have set Title to ""
#RequestMapping(value = "/search",method = RequestMethod.POST)
public String queryByTitle(AdDto adDto, Model model){
List<Ad>adList = adService.queryByTitle(adDto);
model.addAttribute("adList",adList);
model.addAttribute("searchParam",adDto);
return "/content/adList";
}
But after forward, adDto.title doesn's change. I don't know why.
You can see the 'title' change to "芒果冰淇淋11"

I think this response on another question may be helpful:
Spring forward with added parameters?
re-adding what you need to the request before it is forwarded.
Using FlashScope as well should be an option here an example:
https://www.javacodegeeks.com/2012/02/spring-mvc-flash-attributes.html
(in the example it uses "redirec:some/path" but using "forward" as you do should be possible as well)
A link to Spring (4.1) docs for Flash attributes:
https://docs.spring.io/spring/docs/4.1.x/spring-framework-reference/html/mvc.html#mvc-flash-attributes

I finally solved this problem in adding the following code:
Code

Related

Spring Boot Override Wildcard RequestMapping

I am building a URL Shorter app (like Bitly). It is an SPA using Spring Boot & ReactJS. All web content is served off of index.html. All other routes are presumed to be shortLink redirect requests which should trigger a clickShortUrl() function to fetch the corresponding originalLink and redirect the user to that web address.
Therefore, I want the following routes to redirect to index.html:
#GetMapping(value = {"/", "/home", "/dashboard"})
public String redirect() {
return "forward:/index.html";
}
and all other/unknown routes to trigger a wildcard function:
#RequestMapping(value = "/{shortUrl}", method = RequestMethod.GET)
public Object clickShortUrl(#PathVariable("shortUrl") String shortUrl, #RequestBody ClickDTO request) {
// internalLogicHere
};
Individually, the mappings and functions are working. But combined, the /{shortUrl} wildcard route always takes precedence. I've googled around looking for ways to override this behavior. It seems to be possible a few ways, but all of my attempts have failed.
I read several posts like this suggesting to extend WebMvcConfigurerAdapter and override addViewControllers(ViewControllerRegistry registry) to define view controllers for specific routes. I don't really understand this. Is this the right path? If so, can someone help me understand what ViewControllerRegistry is all about and set me on the right path?
Thank you!
Answered my own question. Ended up using RegEx in the wildcard route to exclude the static paths used on the front end.
/** Redirect all '/' and '/dashboard/ requests to index.html. */
#GetMapping(value = {"path:/", "path:/dashboard"})
public String redirect() {
return "forward:/index.html";
}
and the fallback route:
/**
* Treat all routes as /{shortUrl} clicks except: '/', '/index.html, '/dashboard''
*/
#RequestMapping(value = "{_:^(?!index\\.html|dashboard).*$}")
public Object clickShortUrl(#PathVariable("shortUrl") String shortUrl, #RequestBody ClickDTO request) {
// internalLogicHere;
}

Spring Boot with HTML

I hava Spring Boot Application.I want to show html.
index.html location is following
templete/view/index.html
Controller.java
#Controller
public class Controller {
#RequestMapping(value = "/view", method = RequestMethod.GET)
public String index() {
return "/view/index.html";
}
}
return "view/index";
Should be what you need. In the future you might consider saying what you expect to happen and what actually happens, even better providing an error message which might give a hint like your file could not be found.

Preserving model state with Post/Redirect/Get pattern and URL rewriting

First of all, I know that there are similar questions regarding "Preserving model state with Post/Redirect/Get pattern", but none of these have my very specific problem:
background:
My Code is working in an enterprise CMS software which does a lot of things. One of them is URL rewriting: Whenever I generate Links to my controller, dependending on the environment, the links are shortened - That's a SEO thing and can't be discussed.
I.e. if my Controller URL is /webapp/servlet/myController/doSomething, the generated URL will be /myController/doSomething. There's some LinkProcessing functionality that we have to use.
An apache rewrite rule will then expand this short url to /webapp/servlet/myController/doSomething when the apache uses mod_rewrite to call the corresponsing code on the tomcat:
RewriteCond %{REQUEST_URI} ^/myController/(.*)
RewriteRule ^/myController/(.*) /webapp/servlet/myController/$1 [PT,L]
Problem:
I'm trying to implement the Post/Redirect/Get pattern using Spring 3.1.2. I'm generating a form and POST it to the Controller, which validated and makes a redirect to either the success or error page using GET (Post/Redirect/Get pattern).
(highly simplified) Code:
#RequestMapping()
public class MyController {
#RequestMapping(value = "/doDispatch", method = RequestMethod.POST)
public RedirectView handleDispatch(RedirectAttributes redirectAttributes,
#Validated #ModelAttribute FormBean formBean,
BindingResult binding) {
if (binding.hasErrors()) {
redirectAttributes.addFlashAttribute(formBean);
redirectAttributes.addFlashAttribute(BindingResult.MODEL_KEY_PREFIX+"formBean", binding);
return new RedirectView(generateLink("/error"));
} else {
redirectAttributes.addFlashAttribute(formBean);
redirectAttributes.addFlashAttribute(BindingResult.MODEL_KEY_PREFIX+"formBean", binding);
return new RedirectView(generateLink("/success"));
}
}
#RequestMapping(value = "/success")
public ModelAndView handleSuccess(#ModelAttribute FormBean formBean) {
// do stuff (save things in the DB)
// ...
final ModelAndView modelAndView = createModelAndView(formBean);
modelAndView.addObject("success", true);
return modelAndView;
}
#RequestMapping(value = "/error")
public ModelAndView handleError(#Validated #ModelAttribute FormBean formBean,
BindingResult binding) {
final ModelAndView modelAndView = createModelAndView(formBean);
modelAndView.addObject("binding", binding);
modelAndView.addObject("formBean", formBean);
return modelAndView;
}
}
The problem ist that this generateLink() method will either generate links starting with /webapp/servlet or not - depending on the environment/success. And that's how this whole Enterprice CMS thing works. (that's the part which cannot be discussed)
Spring Flash-Attributes on the other hand work hand in hand with the URLs that are returned and store the URL as part of the FlashMap:
Quote from http://docs.spring.io/spring/docs/current/spring-framework-reference/html/mvc.html#mvc-flash-attributes :
To reduce the possibility of such issues, RedirectView automatically "stamps" FlashMap instances with the path and query parameters of the target redirect URL. In turn the default FlashMapManager matches that information to incoming requests when looking up the "input" FlashMap.
Since the next request (let's say I've had an error and returned "/myController/error") will be expanded to /webapp/servlet/myController/error, the FlashMap will not apply to this request, since the URLs do not match.
The code that is responsible is this here (AbstractFlashMapManager.java:157 ff):
protected boolean isFlashMapForRequest(FlashMap flashMap, HttpServletRequest request) {
if (flashMap.getTargetRequestPath() != null) {
String requestUri = this.urlPathHelper.getOriginatingRequestUri(request);
if (!requestUri.equals(flashMap.getTargetRequestPath())
&& !requestUri.equals(flashMap.getTargetRequestPath() + "/")) {
return false;
}
}
// ...
}
Question:
Do you know a way how I can still generate short URLs on the one hand, but pass the FlashAttributes to the following GET request?
Best regards and thanks for your help in advance,
Alexander
The best solution I've found so far is using an Interceptor that updates the targetRequestPath by prefixing /<webappPath>/<servletPath> to those FlashMaps from RequestContextUtils.getOutputFlashMap(request) that are missing this information. BTW: this can only be done in the afterCompletion method, because otherwise the targetRequestPath won't be set at all, when using a RedirectView.
Any other, better solutions?

How to return a variable in every page from my Spring MVC application from the same controller method?

I want to return a model from my Spring MVC controller, which will be visible to all pages in my application.
So, I need a variable which return some user details.
This is my code:
#RequestMapping(value = "/*", method = RequestMethod.GET)
public void status(Model model){
Authentication auth = SecurityContextHolder.getContext()
.getAuthentication();
String username = auth.getName();
Manager mgr = managerService.findOne(username);
model.addAttribute("buget", mgr.getTeam().getTeamBuget());
}
And in my jsp page, i write something like this:
<li> <c:out value="${buget}" /> <span class="glyphicon glyphicon-euro"></span></li>
I want to be able to print the ${buget} in every page from my app.
So, my method don't work, nothing is appear in my pages and the biggest problem
for me is that I don't get any exceptions or errors which could help me. Who can help me with some advices?
I'm not entirely sure what it is that you're trying to do. Do you mean that you want buget to be part of every page that you hit? If so, you have to insert it into the model. Based on your code, I'm assuming that you have the mistaken impression that status is going to be called regardless of whatever page you hit. Spring will resolve to the most-specific handler and so if you have another handler method in another controller that is more specific, Spring will use that. But even if the one you have was called, how would Spring know that it has to call the most-specific one next? So how would you add page-dependent model attributes to the model?
If you want buget to be part of every response, you can use #ControllerAdvice (see here for a blog post with more details):
#ControllerAdvice
public class BugetControllerAdvice {
#ModelAttribute
public void addBugetToModel(Model model) {
Authentication auth = SecurityContextHolder.getContext().getAuthentication();
String username = auth.getName();
Manager mgr = managerService.findOne(username);
model.addAttribute("buget", mgr.getTeam().getTeamBuget());
}
}
Spring will now call this method before every handler-method in every controller. You can also take a look at the Spring Reference for more information.

using spring mvc redirect a url pattern to a specific controller

i would like to redirect a request something like this
localhost:8080 /firstSpringProject/{uniqueusername}
to a specific controller named 'profile':
#RequestMapping(value="/profile")
public String profiles(Model model){
based on the uniqueusername i would like to render a profile page
return "profile";
}
I am using spring mvc; how can I resolve this situation is there any other way to do this?
Spring documentation says on redirect view:
Note that URI template variables from the present request are
automatically made available when expanding a redirect URL and do not
need to be added explicitly neither through Model nor
RedirectAttributes. For example:
#RequestMapping(value = "/files/{path}", method = RequestMethod.POST)
public String upload(...) {
// ...
return "redirect:files/{path}";
}
Keep in mind that version lower than 3.1.4 are affected by a memory leak due to caching redirect views.
If you are using Spring 3.1.3 or lower and you are doing this
return "redirect : profile?username="+username;
you will see OutOfMemoryError sometime.
I think you may use spring path variable here. You have to create a controller method that will take username as per your URL requirement and will redirect to profile method with username parameter.
#RequestMapping(value="/{username}")
public String getUserName(Model model,#PathVariable("username") String username){
//process username here and then redirect to ur profile method
return "redirect : profile?username="+username;
}
#RequestMapping(value="/profile")
public String profiles(Model model,String username){
//have a username and render a profile page
return "profile";
}
Thank you

Categories

Resources