My main problem here is returning a string with a pathvariable value from one controller to another.
See here:
#RequestMapping(value = "/profile/{location}")
public ModelAndView profile(#PathVariable("location") String location) throws Exception {
return new ModelAndView("profile", "*", *);
}
#RequestMapping(value = "/records", method = "RequestMethod.POST")
public String inRecords(#Valid User user, BindingResult result) {
if(result.hasErrors()) {
return "profile/system";
}
else {
.....
return "somewhere";
}
}
My problem here is the return "profile/system" going to WEB-INF/views/profile/system.jsp. Am I doing anything wrong with #PathVariable or with the return statement itself?
Any suggestions?
Why you dont try something like this.
#RequestMapping(value = "/records", method = "RequestMethod.POST")
public void inRecords(#Valid User user, HttpServletResponse response) {
if(result.hasErrors()) {
response.sendRedirect("/YourApp/profile/system")
}
I think ModelAndView is taking the returned String and try to run ViewResolver that try to get the jso, avoid that calling or redirecting the request directly to the needed endpoint.
Or If you want to keep modelAndView use this
return new ModelAndView("redirect:/profile/system");
Related
I have created one ajax call in UI. Through the ajax call, I am sending one String variable as a request param. Now i want to access this request param variable in another method which is in the same class. How to make my request param variable as a public variable.
This is the code.
<script>
$(document).ready(function() {
$("#cDetails").change(function() {
var value1 = $('#cDetails:selected').text();
$.ajax({
type : 'POST',
url : 'envi',
data : {
cname : value1
},
success : function(result) {
}
});
});
});
</script>
This is my controller Layer.
#RequestMapping(value = "/envi", method = RequestMethod.POST)
public #ResponseBody String getEnvironmentNames(#RequestParam String cname) throws SQLException {
System.out.println("cname"+cname);
ModelAndView modelAndView = new ModelAndView();
modelAndView.addObject("environments", new Environments());
List<Environments> environmentnamesList= loginDelegate.getEnvironments(cname);
Gson gson = new Gson();
System.out.println("gson"+gson);
String jsonString = gson.toJson(environmentnamesList);
System.out.println("jsonString"+jsonString);
return jsonString;
}
In this same clas, I want to access this cname varible.
#RequestMapping(value = "/retri", method = RequestMethod.GET)
public ModelAndView test(HttpServletRequest request, HttpServletResponse response,
#ModelAttribute("customer") Customer customer) throws Exception{
system.out.println("cname " + cname);
}
Can any one suggest me.
If the two requests are made by the same client in the same session you can add the cname value to the Session.
getEnvironmentNames(#RequestParam String cname, HttpServletRequest rq){
...
rq.getSession().setAttribute("cname", cname);
...
}
and then in test
test(HttpServletRequest request, HttpServletResponse response,
#ModelAttribute("customer") Customer customer) throws Exception{
system.out.println("cname " + request.getSession().getAttribute("cname"));
}
If it is not the case, you need to store the value of cname in a repository like a Database.
You can declare a variable in class and set it to the value when you pass it the first time. And you can re-use it in any method in the controller.
private String var;
#RequestMapping(value = "/envi", method = RequestMethod.POST)
public #ResponseBody String getEnvironmentNames(#RequestParam String cname) throws SQLException {
System.out.println("cname"+cname);
var=cname;
ModelAndView modelAndView = new ModelAndView();
modelAndView.addObject("environments", new Environments());
List<Environments>
environmentnamesList=loginDelegate.getEnvironments(cname);
Gson gson = new Gson();
System.out.println("gson"+gson);
String jsonString = gson.toJson(environmentnamesList);
System.out.println("jsonString"+jsonString);
return jsonString;
}
and in here
#RequestMapping(value = "/retri", method = RequestMethod.GET)
public ModelAndView test(HttpServletRequest request, HttpServletResponse response,
#ModelAttribute("customer") Customer customer) throws Exception{
system.out.println("cname" + **var**);
}
I'm new to spring mvc , I'm working on a web project admin panel.
Here is some example of my admin pages controllers :
#Controller
#RequestMapping("/admin/article/**")
public class ArticleController {
private ArticleDao articleDao;
private String fileName;
private String baseUrl;
public ArticleController() {
articleDao = ArticleDaoFactory.create();
}
#RequestMapping(value = "/admin/article",method = RequestMethod.GET)
public String doGet(ModelMap model,HttpServletRequest request,ArticleForm articleForm) {
//some codes
}
#RequestMapping(value = "/admin/article/add",method = RequestMethod.GET)
public String doGetAdd(ModelMap model,ArticleForm articleForm) {
model.addAttribute("article", articleForm);
return "admin/articleAdd";
}
#RequestMapping(value = "/admin/article/add",method = RequestMethod.POST)
public String doPost(#ModelAttribute ArticleForm article, BindingResult result ,ModelMap model){
//some codes
}
#RequestMapping(value = "/admin/article/edit/{id}",method = RequestMethod.GET)
public String getEdit(ModelMap model, #PathVariable("id") int id) {
//some codes
}
#RequestMapping(value = "/admin/article/edit/{id}",method = RequestMethod.POST)
public String postEdit(ModelMap model, #PathVariable("id") int id, ArticleForm article, BindingResult result) {
//some codes
}
#RequestMapping(value = "/admin/article/delete/{id}",method = RequestMethod.GET)
public void getDelete(ModelMap model, #PathVariable("id") int id, HttpServletResponse response) {
//some codes
}
}
now I need another mapping in another contoller named AdminController (for example) to Authenticate admin and bring him to login page if he is not logged in. for sure Authenthication is one example, I might want to use more classes on every admin page.
Note that my authenthication class needs request and session references (and for sure my other classes will need other references created by spring)
I got to know that I can not get HttpServletRequest and ... using a constructor method so I wrote another request mapping to call a method.
Eventhough I can set my properties this way ,but I can not use this method on every admin url.
#Controller
#RequestMapping(value = "/admin/**",method = RequestMethod.GET)
public class AdminController {
Authentication authentication;
HttpServletRequest request;
HttpSession session;
HttpServletResponse response;
public void checkAndSet(HttpSession session,HttpServletRequest request,HttpServletResponse response) {
authentication = new Authentication(session,request);
this.request = request;
this.session = session;
this.response = response;
if(!authentication.isLoggedIn()){
System.out.println(" I'm not logged in");
response.setHeader("Location","/admin/login");
}
}
So I need some suggestion on how to write a request mapping in a controller to call a method on every other controllers that are 'admin' page child ?
FYI : I'm not thinking for spring security for this.
thanks;
I think you can do it by implementing a servlet filter.
For example :
public class AuthenticationFilter extends GenericFilterBean {
#Override
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) res;
String url = request.getServletPath();
HttpSession session = request.getSession(false);
Authentication authentication = new Authentication(session,request);
if (isAdminUrl(url) && !authentication.isLoggedIn()) {
res.sendRedirect/admin/login");
}
chain.doFilter(req, res);
}
}
And then, you have to implement the method isAdminUrl(String url) to determine if you want to apply your filter.
Otherwise, I strongly recommend you to take a look at Spring Security
below is my controller
#RequestMapping(method = RequestMethod.GET)
#ResponseBody
public String ABC(Registratio registration, ModelMap modelMap,
HttpServletRequest request,HttpServletResponse response){
if(somecondition=="false"){
return "notok"; // here iam returning only the string
}
else{
// here i want to redirect to another controller shown below
}
}
#RequestMapping(value="/checkPage",method = RequestMethod.GET,)
public String XYZ(ModelMap modelMap,
HttpServletRequest request,HttpServletResponse response){
return "check"; // this will return check.jsp page
}
since the Controller ABC is #ResponceBody type it will always return as string, but i want that in else contion it should be redirected to the XYZ controller and from which it return a jsp page which i can show.
i tried using return "forward:checkPage"; also with return "redirect:checkPage";
but doesn't work.
any help.
Thanks.
I think you have to remove #ResponseBody if you want to either render response yourself or redirect in one controller method based on some condition, try this:
#RequestMapping(method = RequestMethod.GET)
//remove #ResponseBody
public String ABC(Registratio registration, ModelMap modelMap,
HttpServletRequest request,HttpServletResponse response){
if(somecondition=="false"){
// here i am returning only the string
// in this case, render response yourself and just return null
response.getWriter().write("notok");
return null;
}else{
// redirect
return "redirect:checkPage";
}
}
--edit--
if you want to access controller via ajax, you'd better include the datatype parameter on you request to indicate that you are simply expecting a text response:
$.get("/AAA-Web/abc",jQuery.param({})
,function(data){
alert(data);
}, "text");
return new ModelAndView("redirect:/admin/index");
The code above works for me. I was redirecting from the present controller to index in AdminController.
edirected to the XYZ controller and from which it return a jsp page instead of using the following code i/e
#RequestMapping(value="/checkPage",method = RequestMethod.GET,)
public String XYZ(ModelMap modelMap,
HttpServletRequest request,HttpServletResponse response){
return "check"; // this will return check.jsp page
}
use
#RequestMapping(value ="/checkPage",method = RequestMethod.GET)
public ModelAndView XYZ(HttpServletRequest req)
{
ModelAndView m=new ModelAndView();
m.setViewName("check");
return m;
}
I have noticed the following code is redirecting the User to a URL inside the project,
#RequestMapping(method = RequestMethod.POST)
public String processForm(HttpServletRequest request, LoginForm loginForm,
BindingResult result, ModelMap model)
{
String redirectUrl = "yahoo.com";
return "redirect:" + redirectUrl;
}
whereas, the following is redirecting properly as intended, but requires http:// or https://
#RequestMapping(method = RequestMethod.POST)
public String processForm(HttpServletRequest request, LoginForm loginForm,
BindingResult result, ModelMap model)
{
String redirectUrl = "http://www.yahoo.com";
return "redirect:" + redirectUrl;
}
I want the redirect to always redirect to the URL specified, whether it has a valid protocol in it or not and do not want to redirect to a view. How can I do that?
Thanks,
You can do it with two ways.
First:
#RequestMapping(value = "/redirect", method = RequestMethod.GET)
public void method(HttpServletResponse httpServletResponse) {
httpServletResponse.setHeader("Location", projectUrl);
httpServletResponse.setStatus(302);
}
Second:
#RequestMapping(value = "/redirect", method = RequestMethod.GET)
public ModelAndView method() {
return new ModelAndView("redirect:" + projectUrl);
}
You can use the RedirectView. Copied from the JavaDoc:
View that redirects to an absolute, context relative, or current request relative URL
Example:
#RequestMapping("/to-be-redirected")
public RedirectView localRedirect() {
RedirectView redirectView = new RedirectView();
redirectView.setUrl("http://www.yahoo.com");
return redirectView;
}
You can also use a ResponseEntity, e.g.
#RequestMapping("/to-be-redirected")
public ResponseEntity<Object> redirectToExternalUrl() throws URISyntaxException {
URI yahoo = new URI("http://www.yahoo.com");
HttpHeaders httpHeaders = new HttpHeaders();
httpHeaders.setLocation(yahoo);
return new ResponseEntity<>(httpHeaders, HttpStatus.SEE_OTHER);
}
And of course, return redirect:http://www.yahoo.com as mentioned by others.
You can do this in pretty concise way using ResponseEntity like this:
#GetMapping
ResponseEntity<Void> redirect() {
return ResponseEntity.status(HttpStatus.FOUND)
.location(URI.create("http://www.yahoo.com"))
.build();
}
Looking into the actual implementation of UrlBasedViewResolver and RedirectView the redirect will always be contextRelative if your redirect target starts with /. So also sending a //yahoo.com/path/to/resource wouldn't help to get a protocol relative redirect.
So to achieve what you are trying you could do something like:
#RequestMapping(method = RequestMethod.POST)
public String processForm(HttpServletRequest request, LoginForm loginForm,
BindingResult result, ModelMap model)
{
String redirectUrl = request.getScheme() + "://www.yahoo.com";
return "redirect:" + redirectUrl;
}
Another way to do it is just to use the sendRedirect method:
#RequestMapping(
value = "/",
method = RequestMethod.GET)
public void redirectToTwitter(HttpServletResponse httpServletResponse) throws IOException {
httpServletResponse.sendRedirect("https://twitter.com");
}
For me works fine:
#RequestMapping (value = "/{id}", method = RequestMethod.GET)
public ResponseEntity<Object> redirectToExternalUrl() throws URISyntaxException {
URI uri = new URI("http://www.google.com");
HttpHeaders httpHeaders = new HttpHeaders();
httpHeaders.setLocation(uri);
return new ResponseEntity<>(httpHeaders, HttpStatus.SEE_OTHER);
}
For external url you have to use "http://www.yahoo.com" as the redirect url.
This is explained in the redirect: prefix of Spring reference documentation.
redirect:/myapp/some/resource
will redirect relative to the current Servlet context, while a name such as
redirect:http://myhost.com/some/arbitrary/path
will redirect to an absolute URL
Did you try RedirectView where you can provide the contextRelative parameter?
This works for me, and solved "Response to preflight request doesn't pass access control check ..." issue.
Controller
RedirectView doRedirect(HttpServletRequest request){
String orgUrl = request.getRequestURL()
String redirectUrl = orgUrl.replaceAll(".*/test/","http://xxxx.com/test/")
RedirectView redirectView = new RedirectView()
redirectView.setUrl(redirectUrl)
redirectView.setStatusCode(HttpStatus.TEMPORARY_REDIRECT)
return redirectView
}
and enable securty
#EnableWebSecurity
class SecurityConfigurer extends WebSecurityConfigurerAdapter{
#Override
protected void configure(HttpSecurity http) throws Exception {
http.cors().and().csrf().disable()
}
}
In short "redirect://yahoo.com" will lend you to yahoo.com.
where as "redirect:yahoo.com" will lend you your-context/yahoo.com ie for ex- localhost:8080/yahoo.com
I am attempting to set-up a scheme for uniformly handling exceptions in Spring. As such, I need a way to pass context information into an #ExceptionHandler-annotated method, for example consider the following:
#ExceptionHandler(Exception.class)
public void handleException(Exception ex, HttpServletRequest request) {
// Need access to myContext from login()
}
#RequestMapping(value = "{version}/login", method = RequestMethod.POST)
public void login(HttpServletRequest request, #PathVariable String version, #RequestParam("userName") String userName, #RequestParam("password") String password, ModelMap model) throws Exception {
...
myContext = "Some contextual information"
...
i_will_always_throw_an_exception();
}
Since Spring is responsible for translating a thrown exception into an invocation of handleException(), I am having difficulty trying to find a way to pass myContext to the handler. One thought I have is creating a subclass of HttpServletRequest. If that approach works I would have code like this:
#ExceptionHandler(Exception.class)
public void handleException(Exception ex, MyCustomHttpServletRequest request) {
// I now have access to the context via the following
String myContext = request.getContext();
}
#RequestMapping(value = "{version}/login", method = RequestMethod.POST)
public void login(MyCustomHttpServletRequest request, #PathVariable String version, #RequestParam("userName") String userName, #RequestParam("password") String password, ModelMap model) throws Exception {
...
myContext = "Some contextual information"
request.setContext(myContext);
...
i_will_always_throw_an_exception();
}
But, if I follow this approach, how do I properly use my own arbitrary sub-class of HttpServletRequest to make this work?
Can't you just put it into exception (if necessary - wrapping the original exception with the new one)?
#ExceptionHandler(MyContextualException.class)
public void handleException(MyContextualException ex) {
// Need access to myContext from login()
}
#RequestMapping(value = "{version}/login", method = RequestMethod.POST)
public void login(HttpServletRequest request, #PathVariable String version, #RequestParam("userName") String userName, #RequestParam("password") String password, ModelMap model) throws Exception {
...
myContext = "Some contextual information"
...
try {
i_will_always_throw_an_exception();
} catch (Exception ex) {
throw new MyContextualException(myContext, ex);
}
}
An alternative approach is to pass the context as a request attribute:
request.setAttribute("myContext", myContext);