I'm new in concept of forwarding with spring boot and Thymeleaf.
I want to use forwarding in my application from one Controller to another getting sessionAttribute.
I have a placed a form in /home page and when I click on submit button, the for gets submitted to database but the application does not render the next (service.html) page using redirect.
#Controller
#SessionAttributes("user")
public class SavingUser{
#Autowired
private UserRepository userRepository;
#GetMapping("/home")
public String addUser(Model model){
model.addAttribute("user", new Customer());
return "index";
}
#PostMapping("/registerUser")
public Callable <String> userRegistration(#Valid #ModelAttribute("user") Customer user, BindingResult result, Model model, HttpServletRequest request){
---
----
return()->{
if(result.hasErrors()) {
---
}
----
return "redirect:/greetingCustomer";
};
}
Forwarding to another controller -
#Controller
public class GreetingService {
#PostMapping("/greetingCustomer")
public String greetCustomer(#SessionAttribute("user")Customer customer, Model model) throws IOException {
System.out.println("A new user " + customer.getName() + " is trying to request a quote");
model.addAttribute("person",customer.getName());
return "redirect:/service";
}
}
I already have placed the 'service.html' file in classpath.
I used this same concept with JSP and it worked well.
Any idea what the problem is ?
As I can see when you are using return "redirect:/greetingCustomer"; then you can only redirect to the greetingCustomer.
If you want to redirect to the service page the use return "redirect:/service";
Related
this is a general quick question. As my native language isn't english I have trouble searching up on google what I need.
The situation:
I have created a spring application which I can access through "localhost:8080" and which uses spring security and after the login it shows the index.html I have put in the main/resources/static folder.
What I am trying to do:
I want the homepage to be and automatically transfer to "localhost:8080/home" or "localhost:8080/index" instead of just being "localhost:8080"
My controller class :
package com.lukas.ramonas.cms.DAO;
import com.lukas.ramonas.cms.Model.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
import java.util.Collection;
#Controller // This means that this class is a Controller
#RequestMapping(path="/home") // This means URL's start with /home (after Application path)
public class MainController {
// This means to get the bean called user_tableRepository
// Which is auto-generated by Spring, we will use it to handle the data
// #GetMapping("/index")
// public String index() {
// return "index";
// }
#Autowired
private UserRepository UserRepository;
#PostMapping(path="/add") // Map ONLY POST Requests
public #ResponseBody String addNewUser (
#RequestParam String name,
#RequestParam String username,
#RequestParam String password,
#RequestParam String email,
#RequestParam Collection roles,
#RequestParam Boolean confirmed) {
// #ResponseBody means the returned String is the response, not a view name
// #RequestParam means it is a parameter from the GET or POST request
User n = new User();
n.setName(name);
n.setUsername(username);
n.setPassword(password);
n.setEmail(email);
n.setRole(roles);
n.setConfirmed(confirmed);
UserRepository.save(n);
return "Saved";
}
#GetMapping(path="/all")
public #ResponseBody Iterable<User> getAllUsers() {
// This returns a JSON or XML with the users
return UserRepository.findAll();
}
}
If any extra info or code is needed I am happy to provide.
#RequestMapping does accept multiple mappings, not just a single one:
You can add like this:
#GetMapping(value = {"/", "/home", "/index"})
public String index() {
return "index";
}
per default spring security will return you back to the original forbidden url you tried to access.
So for instance, if you try to access http://locahost:8080/foobar and you are unauthenticated you will get a 302 Redirect to /login, when successfully authenticated, you get a 302 Redirect back to /foobar.
If you wish to override this behaviour you can do this in several ways.
You can either set the successForwardUrl in your HttpSecurity config:
http.formLogin()
.successForwardUrl("/foobar")
or you can implement the interface AuthenticationSuccessHandler
http.formLogin()
.successHandler(customAuthenticationSuccessHandler)
and build a custom redirect response:
public class CustomAuthenticationSuccessHandler implements AuthenticationSuccessHandler {
#Override
public void onAuthenticationSuccess(
HttpServletRequest request,
HttpServletResponse response,
Authentication authentication
) throws IOException, ServletException {
// Mutate the response here
}
}
I am developing a web app using spring boot and mvc. I have controllers and in every controller i have to check if session is exist. In example in getAll method i am checking if session is existing but i have to write this check code in every method , every controller. Is there any shortcut to do that?
#Controller
#RequestMapping("/Sale")
public class SaleController
{
#Autowired
private SaleRepository saleRepository;
#GetMapping
public ModelAndView getAll(#SessionAttribute(required=false) User user)
{
if(user==null)
return new ModelAndView("redirect:/");
else
{
ModelAndView modelAndView=new ModelAndView("/view/sales.jsp");
List<Sale> sales=saleRepository.findAll();
modelAndView.addObject("sales",sales);
return modelAndView;
}
}
}
You can use a Filter and apply it to all requests or only those matching a specific pattern.
To check for a session you would use HttpServletRequest.getSession(false) and check for null.
I am doing a simple spring MVC project. There are three jsp pages page 1, page 2 and page 3. In page 1 and page 2 I have user form and I want to print two user's details in page 3. I think it could be solved using spring mvc annotation #ModelAttribute and #SessionAttribute but I don't know how to use them.
If anyone have any idea about my problem, please help me with a simple example
It's documented in Spring Framework's documentation:
http://docs.spring.io/spring/docs/current/spring-framework-reference/htmlsingle/#mvc-ann-sessionattrib
#Controller
#SessionAttributes(value = {"user1", "user2"})
public class MyController {
// ...
#GetMapping("/page1")
public String page1(ModelMap model){
model.put("user", new User());
return "page1";
}
#PostMapping("/page1")
public String page1Post(#ModelAttribute("user") User user, ModelMap model{
model.put("user1", user);
model.put("user", new User());
return "page2";
}
#PostMapping("/page2")
public String page2Post(#ModelAttribute("user") User user, ModelMap model{
model.put("user2", user);
return "page3";
}
}
With this user1 and user2 will be available in your page3
I'd like to know if there is a way I can forward a request from one controller to another without actually changing the URL in the browser.
#RequestMapping(value= {"/myurl"})
public ModelAndView handleMyURL(){
if(somecondition == true)
//forward to another controller but keep the url in the browser as /myurl
}
examples that I found online were redirecting to another url which was causing other controllers to handle that. I don't want to change the URL.
Try to return a String instead of ModelAndView, and the String being the forward url.
#RequestMapping({"/myurl"})
public String handleMyURL(Model model) {
if(somecondition == true)
return "forward:/forwardURL";
}
Instead of forwarding, you may just call the controller method directly after getting a reference to it via autowiring. Controllers are normal spring beans:
#Controller
public class MainController {
#Autowired OtherController otherController;
#RequestMapping("/myurl")
public String handleMyURL(Model model) {
otherController.doStuff();
return ...;
}
}
#Controller
public class OtherController {
#RequestMapping("/doStuff")
public String doStuff(Model model) {
...
}
}
As far as I know "forward" of a request will be done internally by the servlet, so there will not be a second request and hence the URL should remain the same. Try using the following code.
#RequestMapping(value= {"/myurl"})
public ModelAndView handleMyURL(){
if(somecondition == true){
return new ModelAndView("forward:/targetURL");
}
}
I want to read a domain object (UserVO) from session scope.
I am setting the UserVO in a controller called WelcomeController
#Controller
#RequestMapping("/welcome.htm")
public class WelcomeController {
#RequestMapping(method = RequestMethod.POST)
public String processSubmit(BindingResult result, SessionStatus status,HttpSession session){
User user = loginService.loginUser(loginCredentials);
session.setAttribute("user", user);
return "loginSuccess";
}
}
I am able to use the object in jsp pages <h1>${user.userDetails.firstName}</h1>
But I am not able to read the value from another Controller,
I am trying to read the session attribute as follows:
#Controller
public class InspectionTypeController {
#RequestMapping(value="/addInspectionType.htm", method = RequestMethod.POST )
public String addInspectionType(InspectionType inspectionType, HttpSession session)
{
User user = (User) session.getAttribute("user");
System.out.println("User: "+ user.getUserDetails().getFirstName);
}
}
The code you've shown should work - the HttpSession is shared between the controllers, and you're using the same attribute name. Thus something else is going wrong that you're not showing us.
However, regardless of whether or not it works, Spring provides a more elegant approach to keeping your model objects in the session, using the #SessionAttribute annotation (see docs).
For example (I haven't tested this, but it gives you the idea):
#Controller
#RequestMapping("/welcome.htm")
#SessionAttributes({"user"})
public class WelcomeController {
#RequestMapping(method = RequestMethod.POST)
public String processSubmit(ModelMap modelMap){
User user = loginService.loginUser(loginCredentials);
modelMap.addtAttribute(user);
return "loginSuccess";
}
}
and then
#Controller
#SessionAttributes({"user"})
public class InspectionTypeController {
#RequestMapping(value="/addInspectionType.htm", method = RequestMethod.POST )
public void addInspectionType(InspectionType inspectionType, #ModelAttribute User user) {
System.out.println("User: "+ user.getUserDetails().getFirstName);
}
}
However, if your original code isn't working, then this won't work either, since something else is wrong with your session.
#SessionAttributes works only in context of particular handler, so attribute set in WelcomeController will be visible only in this controller.
Use a parent class to inherit all the controllers and use SessionAttributes over there. Just that this class should be in the package scan of mvc.
May be you have not set your UserVO as Serializable.