Login Logout Session in spring mvc - spring

I am trying to implement Login Logout functionality for my project website. I'm making SPA. what is the best way to make login/logout global i.e. if I click on any other link like contact us or about us after logging in logout remains till clicked? Where I'm going wrong How to correct it?
What logic shall I apply so that logout remains till the end?
I have used javascript to change login button to logout
What I want to know is how do I get a login/logout button to display across the entire portal and our unauthenticated site based on if the user is logged in or out? Is it possible for me to execute my code on the header somehow? Or do you have any other suggestions? Currently when I click on signin button then value of temp is passed true and logout button is displayed but now when I click on any other page like about us value of temp hasn't been passed true ..so how to do this across complete portal?
UserController.java
#RequestMapping("/login")
public ModelAndView loginHere() {
log.debug("Starting of the method loginHere");
System.out.println("loginHere");
ModelAndView mv = new ModelAndView("/home");
mv.addObject("user", user);
mv.addObject("isUserClickedLoginHere", "true");
mv.addObject("message", "Welcome to login page");
log.debug("Ending of the method loginHere");
System.out.println("Ending login here");
return mv;
}
#RequestMapping(value = "/validate", method = RequestMethod.GET)
public ModelAndView validate(#RequestParam(value = "username") String userID,
#RequestParam(value = "password") String password) {
log.debug("Starting of the method validate");
System.out.println("validate");
ModelAndView mv = new ModelAndView("/home");
user = userDAO.validate(userID, password);
// if the record exist with this userID and password it will return user
// details else will return null
if (user != null) {
log.debug("Valid Credentials");
session = req.getSession();
/* session.setMaxInactiveInterval(1*10);
*/
session.setAttribute("loggedInUser", user.getName());
session.setAttribute("loggedInUserID", user.getUsername());
session.setAttribute("user", user);
mv.addObject("homePagee", "true");
mv.addObject("temp", "true");
if (user.getRole().equals("ROLE_ADMIN")) {
log.debug("Logged in as Admin");
mv.addObject("isAdmin", "true");
/*
* session.setAttribute("supplier", supplier);
* session.setAttribute("supplierList", supplierDAO.list());
*
* session.setAttribute("category", category);
* session.setAttribute("categoryList", categoryDAO.list());
*/
} else {
log.debug("Logged in as User");
mv.addObject("isAdmin", "false");
// myCart = cartDAO.list(userID);
/*
* mv.addObject("myCart", myCart); // Fetch the myCart list
* based on user ID List<MyCart> cartList =
* cartDAO.list(userID); mv.addObject("cartList", cartList);
* mv.addObject("cartSize", cartList.size());
*/
}
} else {
log.debug("Invalid Credentials");
mv.addObject("invalidCredentials", "true");
mv.addObject("errorMessage", "Invalid Credentials");
}
log.debug("Ending of the method validate");
return mv;
}
#RequestMapping("/logout")
public ModelAndView logout(HttpServletRequest request, HttpServletResponse response) {
log.debug("Starting of the method logout");
System.out.println("Starting of the method logout");
ModelAndView mv = new ModelAndView("/home");
session.invalidate();
session = request.getSession(true);
mv.addObject("homePagee", "true");
mv.addObject("temp1", "true");
Authentication auth = SecurityContextHolder.getContext().getAuthentication();
if (auth != null) {
new SecurityContextLogoutHandler().logout(request, response, auth);
}
System.out.println("Ending of the method logout");
log.debug("Ending of the method logout");
return mv;
// return "redirect:/login?logout";
}
Logout.JSP
<c:if test="${temp}">
<script type="text/javascript">
/* var loginbtn = document.getElementById("login-btn");
var signupbtn = document.getElementById("signup-btn");
var myaccountbtn = document.getElementById("logout-btn");
signupbtn.innerHTML = "";
loginbtn.innerHTML = "";
myaccountbtn.style.display = "block";
*/
/* loginbtn.href = "logout";
*/
</script>
</c:if>
<c:if test="${temp1}">
<script>
var loginbtn = document.getElementById("login-btn")
var signupbtn = document.getElementById("signup-btn")
var myaccountbtn = document.getElementById("logout-btn");
loginbtn.innerhtml = "Login";
signupbtn.innerHTML = "Signup";
loginbtn.href = "login";
myaccountbtn.style.display = "none";
</script>
</c:if>
Login.jsp
<div class="container">
<div class="card card-container">
<!-- <img class="profile-img-card" src="//lh3.googleusercontent.com/-6V8xOA6M7BA/AAAAAAAAAAI/AAAAAAAAAAA/rzlHcD0KYwo/photo.jpg?sz=120" alt="" /> -->
<img id="profile-img" class="profile-img-card"
src="//ssl.gstatic.com/accounts/ui/avatar_2x.png" />
<p id="profile-name" class="profile-name-card"></p>
<form class="form-signin" action="validate">
<span id="reauth-email" class="reauth-email"></span> <input
type="username" name="username" id="inputEmail"
class="form-control" placeholder="Username" required autofocus>
<input type="password" name="password" id="inputPassword"
class="form-control" placeholder="Password" required> <input
type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}" />
<div id="remember" class="checkbox">
<label> <input type="checkbox" value="remember-me">
Remember me
</label>
</div>
<button class="btn btn-lg btn-primary btn-block btn-signin"
type="submit">Sign in</button>
</form>
<!-- /form -->
Forgot the password?
</div>
<!-- /card-container -->
</div>
<!-- /container -->
</div>
Header.jsp
<li class="upper-links"><a class="links" id="signup-btn"
href="register">Signup</a></li>
<li class="upper-links"><a class="links" id="login-btn"
href="login">Login</a></li>
<li class="upper-links dropdown"><a
class="dropdown-toggle links" data-toggle="dropdown" role="button"
aria-haspopup="true" aria-expanded="false" id="logout-btn"
href="loginHere" style="display: none;">My Account<span class="caret"></span></a>
<ul class="dropdown-menu" style="width: 40%;">
<li>Account</li>
<li>Orders</li>
<li>Wishlist</li>
<li role="separator" class="divider"></li>
<li>Logout</li>
</ul></li>

You can user Http Session for track user and handle user login/ logout to your project, Base on session you can implement other business logic to your project.
Simple Login/ Logout In controller :
#PostMapping("/dologin")
public String userLogin(HttpSession session, #ModelAttribute("user") User
user, Model model) {
if (user.getEmail().equals("imranmadbar#gmail.com") &&
user.getPassword().equals("12345")) {
user.setFname("MD IMRAN");
user.setMname("HOSSAIN");
user.setLname("BABU");
user.setAge(28);
session.setAttribute("user", user);
} else {
model.addAttribute("message", "Login failed. Try again.");
return "login";
}
return "redirect:/user/info";
}
#GetMapping("/logout")
public String logout(HttpSession session ) {
session.invalidate();
return "redirect:/login";
}
#GetMapping("/info")
public String userInfo(HttpSession session) {
return "user";
}
After Login user and set user data on session scope you can access those data from any in the project.
Access data from user.jsp File:
<%# page language="java" contentType="text/html; charset=ISO-8859-1"
pageEncoding="ISO-8859-1"%>
<%# page isELIgnored = "false" %>
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>BORAJI.COM</title>
</head>
<body>
<h4>User name: ${user.fname} ${user.mname} ${user.mname}</h4>
<h4>User Age: ${user.age}</h4>
<h4>User Email: ${user.email}</h4>
Log out<br>
</body>
</html>
In my project i track user using spring interceptor.
You can check out my project use this link
https://github.com/imrangthub/LoginRegUsingSession/tree/master/LoginRegUsingSession

Related

Thymeleaf not loading content when I add validation in Spring Boot

Intro:
My app works in the general sense. All as I want. But when I set up validation (and it does work), it won't load all my hidden content. I moved it all to its own page, and it still did not work. So I am asking here with my original set up. I understand it is messy, but I will clean it up once I figure this out.
I can't find anything related to my problem, which makes me think, the way that I am doing it might not be the best approach. So pointers are more than welcome.
Problem:
Adding Validation to my forms breaks my Thymeleaf template. Unable to hide and unhide elements. It looks stuck. But on the terminal, the program does run fine.
My controller
(it's big... I still need to learn how to break it in smaller chunks.)
#Controller
#SessionAttributes({"guess", "word", "result", "level", "attempt", "message", "credits", "name", "gameScore"})
public class GameController {
private static final String WORD_TO_GUESS_CONSTANT = "WORD_TO_GUESS";
private static final String GUESSED_WORD_CONSTANT = "GUESSED_WORD";
private static final String RESULT_CONSTANT = "RESULT_WORD";
private static final String ATTEMPTS_CONSTANT = "ATTEMPTS";
private static final String TOTAL_ATTEMPTS_CONSTANT = "TOTAL_ATTEMPTS";
private static final String MESSAGE_CONSTANT = "MESSAGE";
private static final String CREDITS_CONSTANT = "CREDITS";
private static final String SELECTED_LEVEL_CONSTANT = "SELECTED_LEVEL";
private static final String NAME_CONSTANT = "NAME";
private static final String GAME_SCORE_CONSTANT = "GAME_SCORE";
private static final String SCORE_MULTIPLIER_CONSTANT = "SCORE_MULTIPLIER";
#Autowired
private RandomWordService randomWord;
#Autowired
private WordCheckService checkGuess;
#Autowired
private IsWordCorrectService isWordCorrectService;
#Autowired
private ScoreSavingService scoreSavingService;
#ModelAttribute("gameDto")
public GameDTO guessDTOForm() {
return new GameDTO();
}
#ModelAttribute("score")
public Score score() {
return new Score();
}
// GAME METHODS
#GetMapping(value = "/index")
public String home(Model model,
final HttpServletRequest request,
final HttpSession session,
GameDTO gameDTO,
Score score) {
model.addAttribute("name", session.getAttribute(NAME_CONSTANT));
model.addAttribute("levelSelected", session.getAttribute(SELECTED_LEVEL_CONSTANT));
model.addAttribute("attempt", session.getAttribute(ATTEMPTS_CONSTANT));
model.addAttribute("credits", session.getAttribute(CREDITS_CONSTANT));
model.addAttribute("attemptStart", session.getAttribute(TOTAL_ATTEMPTS_CONSTANT));
model.addAttribute("guess", session.getAttribute(GUESSED_WORD_CONSTANT));
model.addAttribute("result", session.getAttribute(RESULT_CONSTANT));
model.addAttribute("message", session.getAttribute(MESSAGE_CONSTANT));
model.addAttribute("gameScore", session.getAttribute(GAME_SCORE_CONSTANT));
model.addAttribute("lvlName", Level.values());
return "index";
}
#PostMapping(value = "/loadgame")
public String loadWord(
final HttpSession session, final HttpServletRequest request,
#ModelAttribute("score") Score score,
#Valid GameDTO gameDTO, BindingResult bindingResult,
Model model
) throws IOException {
if (bindingResult.hasErrors()) {
model.addAttribute("lvlName", Level.values());
model.addAttribute("name", session.getAttribute(NAME_CONSTANT));
model.addAttribute("levelSelected", session.getAttribute(SELECTED_LEVEL_CONSTANT));
model.addAttribute("attempt", session.getAttribute(ATTEMPTS_CONSTANT));
model.addAttribute("credits", session.getAttribute(CREDITS_CONSTANT));
model.addAttribute("attemptStart", session.getAttribute(TOTAL_ATTEMPTS_CONSTANT));
model.addAttribute("guess", session.getAttribute(GUESSED_WORD_CONSTANT));
model.addAttribute("result", session.getAttribute(RESULT_CONSTANT));
model.addAttribute("message", session.getAttribute(MESSAGE_CONSTANT));
model.addAttribute("gameScore", session.getAttribute(GAME_SCORE_CONSTANT));
return "index";
}
// NEW GAME
String word = (String) request.getSession().getAttribute(WORD_TO_GUESS_CONSTANT);
if (word == null) {
request.getSession().setAttribute(NAME_CONSTANT, gameDTO.getPlayerName());
request.getSession().setAttribute(ATTEMPTS_CONSTANT, gameDTO.getLvlName().getAttempts());
request.getSession().setAttribute(WORD_TO_GUESS_CONSTANT, randomWord.selectRandomWord());
request.getSession().setAttribute(CREDITS_CONSTANT, gameDTO.getCredit());
request.getSession().setAttribute(SELECTED_LEVEL_CONSTANT, gameDTO.getLvlName().getLvlName());
request.getSession().setAttribute(TOTAL_ATTEMPTS_CONSTANT, gameDTO.getLvlName().getAttempts());
request.getSession().setAttribute(GAME_SCORE_CONSTANT, gameDTO.getScore());
request.getSession().setAttribute(SCORE_MULTIPLIER_CONSTANT, gameDTO.getLvlName().getMultiplier());
gameDTO.setWord((String) session.getAttribute(WORD_TO_GUESS_CONSTANT));
}
model.addAttribute("message", "");
return "redirect:/index";
}
#PostMapping(value = "/guess")
public String guessWord(
final HttpSession session,
final HttpServletRequest request,
#ModelAttribute("score") Score score,
#Valid GameDTO gameDTO, BindingResult bindingResult) throws IOException {
if (bindingResult.hasErrors()) {
return "index";
}
// variables
int attempts = (int) session.getAttribute(ATTEMPTS_CONSTANT);
int credits = (int) session.getAttribute(CREDITS_CONSTANT);
int startAttempts = (int) session.getAttribute(TOTAL_ATTEMPTS_CONSTANT);
String name = (String) session.getAttribute(NAME_CONSTANT);
// check word
String wordToGuess = (String) session.getAttribute(WORD_TO_GUESS_CONSTANT);
String guess = gameDTO.getGuess();
String result = checkGuess.resultWord(wordToGuess, guess);
String lvl = (String) session.getAttribute(SELECTED_LEVEL_CONSTANT);
// adjust score according to result
boolean wordIsCorrect = isWordCorrectService.isTheWordCorrect(result, wordToGuess);
int gameScore = (int) session.getAttribute(GAME_SCORE_CONSTANT);
int scoreMultiplier = (int) request.getSession().getAttribute(SCORE_MULTIPLIER_CONSTANT);
int wrongWord = gameDTO.getWrongWord();
int initialScore = gameDTO.getStartScore();
int finalScorePerWord = initialScore * scoreMultiplier;
// GAME LOGIC
if (!wordIsCorrect) {
String message = "";
message = "Wrong! Try again!";
request.getSession().setAttribute(MESSAGE_CONSTANT, message);
request.getSession().setAttribute(ATTEMPTS_CONSTANT, --attempts);
request.getSession().setAttribute(GAME_SCORE_CONSTANT, gameScore - wrongWord);
log(GameController.class, "Updated score: " + session.getAttribute(GAME_SCORE_CONSTANT));
if (attempts == 0) {
request.getSession().setAttribute(CREDITS_CONSTANT, --credits);
message = "Sorry, the word was: [ " + session.getAttribute(WORD_TO_GUESS_CONSTANT) + " ]";
request.getSession().setAttribute(MESSAGE_CONSTANT, message);
request.getSession().setAttribute(ATTEMPTS_CONSTANT, startAttempts);
request.getSession().setAttribute(WORD_TO_GUESS_CONSTANT, randomWord.selectRandomWord());
}
if (credits == 0) {
message = "Game over!";
request.getSession().setAttribute(MESSAGE_CONSTANT, message);
request.getSession().setAttribute(GAME_SCORE_CONSTANT, gameScore);
// SAVE SCORE
score.setGameScore(gameScore);
score.setName(name);
score.setSelectedLevelName(lvl);
scoreSavingService.saveScore(score);
log(GameController.class, "Final score: " + session.getAttribute(GAME_SCORE_CONSTANT));
}
} else {
String message = "Correct! Guess another word!";
wordToGuess = randomWord.selectRandomWord();
gameDTO.setWord(wordToGuess);
request.getSession().setAttribute(MESSAGE_CONSTANT, message);
request.getSession().setAttribute(WORD_TO_GUESS_CONSTANT, wordToGuess);
request.getSession().setAttribute(ATTEMPTS_CONSTANT, startAttempts);
request.getSession().setAttribute(GAME_SCORE_CONSTANT, gameScore + finalScorePerWord);
log(GameController.class, "Current score 2: " + session.getAttribute(GAME_SCORE_CONSTANT));
}
request.getSession().setAttribute(GUESSED_WORD_CONSTANT, guess);
request.getSession().setAttribute(RESULT_CONSTANT, result);
log(GameController.class, "Attempts are now: " + session.getAttribute(ATTEMPTS_CONSTANT));
return "redirect:/index";
}
// BUTTONS
#PostMapping(value = "/save")
public String giveUpAndSaveScore(final HttpSession session,
final HttpServletRequest request,
#ModelAttribute("score") Score score) {
score.setGameScore((Integer) session.getAttribute(GAME_SCORE_CONSTANT));
score.setName((String) session.getAttribute(NAME_CONSTANT));
score.setSelectedLevelName((String) session.getAttribute(SELECTED_LEVEL_CONSTANT));
scoreSavingService.saveScore(score);
request.getSession().invalidate();
return "index";
}
#GetMapping(value = "/scores")
public String seeScores(final HttpServletRequest request, Model model) {
List<Score> scoreList = scoreSavingService.getScore(5, 1);
model.addAttribute("score", scoreList);
return "scores";
}
// CLOSE SESSION
#PostMapping(value = "/destroy")
public String restartGame(final HttpServletRequest request) {
log(GameController.class, " Session closing. Removing the data.");
request.getSession().invalidate();
return "redirect:/index";
}
// EXCEPTION HANDLERS
#ExceptionHandler(value = ArrayIndexOutOfBoundsException.class)
public String handleArrayIndexOutOfBoundsException(final Model model) {
String text = "ERROR: Could not check empty <<guess>>.";
model.addAttribute("text", text);
return "ExceptionPage";
}
#ExceptionHandler(value = NullPointerException.class)
public String handleNullPointerException(final Model model) {
String text = "ERROR: Cannot compare words because <<word to guess>> is null";
model.addAttribute("text", text);
return "ExceptionPage";
}
}
Thymeleaf template for index.html
<!DOCTYPE html SYSTEM "http://www.thymeleaf.org/dtd/xhtml1-strict-thymeleaf-4.dtd">
<html lang="en" xmlns:th="www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>5Letters</title>
<link th:href="#{/bootstrap.min.css}" rel="stylesheet" />
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Quicksand&display=swap" rel="stylesheet">
</head>
<body>
<div class="container-sm">
<div class="col-xs-12" align="center">
<!-- HEADER -->
<img src="https://marisabel.nl/wp-content/uploads/2020/11/avatar-e1606738130828-150x150.png"
style="margin-top:2vh;">
<h1 style="margin-top:1vh; color:hotpink;"><b>5Letter Word Game</b></h1>
<h5>AKA: Lingo.</h5>
<hr>
</div>
<form method="get" th:action="#{/scores}">
<input type="submit" value="scores" class="btn btn-primary" />
</form>
<!-- Set Up Game Form -->
<div class="col-xs-12" align="center" th:hidden="${credits} != null">
<form th:action="#{/loadgame}" th:object="${gameDTO}" method="post">
<p>
<select class="form-group" th:field="*{lvlName}" id="dropDownList">
<option th:each="lvl : ${lvlName}" th:text="${lvl.lvlName}" th:value="${lvl.lvlName}">
</option>
</select>
</p>
<p><input type="text" class="form-group mx-sm-3 mb-2" id="name" th:field="*{playerName}"
th:placeholder="name" th:value="anonymous" /></p>
<p class="alert alert-danger" th:if="${#fields.hasErrors('playerName')}" th:errors="*{playerName}">
</p>
<p><input type="submit" value="start" class="btn btn-primary" /></p>
</form>
<p></p>
</div>
<!-- This whole session will load after name and level are chosen. Credits will be set to 3, triggering them to unhide -->
<div class="row">
<div class="col-xs-12 col-md-6" align="center" th:hidden="${credits} == null">
<!-- game information : always show after game setup -->
<h3 th:text="'Hello ' + ${name} + '!'"></h3>
<h3 th:text="'Level: '+ ${levelSelected}"></h3>
<h2 th:text="'Credits : '+ ${credits} + ' | Score: '+ ${gameScore}"></h2>
<h2 th:text="${attempt} + ' / ' + ${attemptStart}"></h2>
</div>
<div class="col-md-6" align="center">
<p>
<!-- Result messages and word after guessing -->
<h4 th:text="${message}"></h4>
<h2 id="result" th:text="${result}" th:hidden="${credits} == 0"></h2>
<!-- GUESS FORM -->
<form th:action="#{/guess}" th:object="${gameDTO}" method="post" th:hidden="${credits} == null">
<input id="guessField" type="text" th:field="*{guess}" placeholder="5letters" />
<p></p>
<p class="alert alert-danger" th:if="${#fields.hasErrors('guess')}" th:errors="*{guess}"></p>
<input type="submit" value="guess" th:disabled="${credits} == 0" class="btn btn-primary" />
</form>
</p>
</div>
</div>
<div class="row" style="margin-top:10vh;">
<div class="row justify-content-center" th:hidden="${credits} == null">
<div class="col col-lg-2 align-items-center">
<!-- Destroy session data and go to index -->
<form method="post" th:action="#{/destroy}">
<input type="submit" value="play again" class="btn btn-danger" />
</form>
<p></p>
</div>
<div class="col-md-auto align-items-center" width="50%">
<!-- Display last typed word -->
<h4 th:text="'Your guess was:'" th:hidden="${attempt} == ${attemptStart}"></h4>
<h2 id="guess" th:text="${guess}" th:hidden="${attempt} == ${attemptStart}"></h2>
<p></p>
</div>
<div class="col col-lg-2 align-items-center">
<!-- Stops the game if you are bored. Usually needed with EASY mode. -->
<form method="post" th:action="#{/save}">
<input type="submit" value="i'm tired" class="btn btn-danger" />
<p></p>
</form>
</div>
</div>
</div>
</body>
</html>
I moved the content I was hiding to its own page. It loads the page, but the content remains hidden. Even after taking a break I am still unable to find what is wrong. Specially when it works 100% without validation.

Error resolving template [create], template might not exist or might not be accessible by any of the configured Template Resolvers

I can't figure out why I keep getting this status = 500 template error.
''There was an unexpected error (type=Internal Server Error, status=500).
Error resolving template [create], template might not exist or might not be accessible by any of the configured Template Resolvers
org.thymeleaf.exceptions.TemplateInputException: Error resolving template [create], template might not exist or might not be accessible by any of the configured Template Resolvers''
I tried looking up resources and I coundn't resolve it.
This is what IntelliJ is saying:
This is my create.html template:
<html lang="en" xmlns:th="https://www.thymeleaf.org/">
<head th:replace="fragments :: head"></head>
<head>
<link th:href="#{/css/meetups.css}" rel="stylesheet" />
</head>
<body class="create-meetup-body">
<header th:replace="fragments :: header"></header>
<div class="navbar">
<div class="container">
<nav>
<ul class="meetup-nav">
<li>All Meetups
Create a Meetup
Delete a Meetup</li>
</ul>
</nav>
</div>
</div>
<section class="create-meetup-section">
<form method="post">
<div class="form-group">
<div class="form-wrapper">
<label class="form-name">Meetup Name:
<input th:field="${meetup.meetupName}" class="form-control">
</label>
<p class="error" th:errors="${meetup.meetupName}"></p>
<label class="form-email">Contact Email:
<input th:field="${meetup.meetupContactEmail}" class="form-control">
</label>
<p class="error" th:errors="${meetup.meetupContactEmail}"></p>
<!--label class="form-date">Date:
<input type="date" class="form-control">
</label-->
<label class="form-date">Date (mm/dd/yyy):
<input th:field="${meetup.meetupDate}" class="form-control">
</label>
<p class="error" th:errors="${meetup.meetupDate}"></p>
<label class="form-description">Description:
<textarea th:field="${meetup.meetupDescription}" class="form-control"></textarea>
</label>
<p class="error" th:errors="${meetup.meetupDescription}"></p>
<label class="form-category" th:for="category">Category:</label>
<select id="meetupCategory" name="meetupCategory">
<option value="Nature Walk">Nature Walk</option>
<option value="Cycling">Cycling</option>
<option value="Family Activity">Family Activity</option>
<option value="Athletic">Athletic</option>
</select>
<label class="form-trail" th:for="trail">Trail:</label>
<select name="trailId">
<option th:each="trail : ${trails}"
th:text="${trail.name}"
th:value="${trail.id}"></option>
</select>
</div>
</div>
<input type="submit" value="Create Meetup">
</div>
</form>
</section>
</body>
</html>
I believe create.html it's in the correct directory:
This is my controller class:
#RequestMapping("meetups")
public class MeetupController {
#Autowired
private MeetupRepository meetupRepository;
#Autowired
private TrailRepository trailRepository;
#Autowired
private AuthenticationController authenticationController;
#GetMapping
public String displayMeetups(Model model, HttpServletRequest request) {
HttpSession session = request.getSession(false);
if (session != null) {
User theUser = authenticationController.getUserFromSession(session);
model.addAttribute("theUser", theUser);
}
model.addAttribute("title", "Trail Meetups");
model.addAttribute("meetups", meetupRepository.findAll());
model.addAttribute("trails", trailRepository.findAll());
return "meetups/index";
}
#GetMapping("create")
public String displayCreateMeetupsForm(Model model) {
model.addAttribute("title", "Create A New Meetup");
model.addAttribute("trails", trailRepository.findAll());
model.addAttribute(new Meetup());
return "meetups/create";
}
#PostMapping("create")
public String processCreateMeetupsForm(#ModelAttribute #Valid Meetup newMeetup,
Errors errors, Model model, #RequestParam int trailId) {
if (errors.hasErrors()) {
model.addAttribute("title", "Create A New Meetup");
return "create";
}
Optional<Trail> trailObjs = trailRepository.findById(trailId);
if (trailObjs.isPresent()) {
Trail trail = trailObjs.get();
model.addAttribute("trail", trail);
model.addAttribute("trailId", trailId);
newMeetup.setTrail(trail);
meetupRepository.save(newMeetup);
model.addAttribute("meetups", meetupRepository.findAll());
return "meetups/index";
} else {
return "redirect:";
}
}
#GetMapping("delete")
public String displayDeleteMeetupsForm(Model model, HttpServletRequest request) {
HttpSession session = request.getSession(false);
if (session != null) {
User theUser = authenticationController.getUserFromSession(session);
model.addAttribute("theUser", theUser);
}
model.addAttribute("title", "Delete A Meetup");
model.addAttribute("meetups", meetupRepository.findAll());
return "meetups/delete";
}
#PostMapping("delete")
public String processDeleteMeetupsForm(#RequestParam(required = false) int[] meetupIds, Model model, HttpServletRequest request) {
HttpSession session = request.getSession(false);
if (session != null) {
User theUser = authenticationController.getUserFromSession(session);
model.addAttribute("theUser", theUser);
}
if (meetupIds != null) {
for (int id : meetupIds) {
meetupRepository.deleteById(id);
}
}
return "redirect:";
}
#GetMapping("details")
public String displayMeetupDetails(#RequestParam Integer meetupId, Model model, HttpServletRequest request) {
HttpSession session = request.getSession(false);
if (session != null) {
User theUser = authenticationController.getUserFromSession(session);
model.addAttribute("theUser", theUser);
}
Optional<Meetup> result = meetupRepository.findById(meetupId);
if (result.isEmpty()) {
model.addAttribute("title", "Invalid: A meetup with ID " + meetupId + "does not seem to exist.");
} else {
Meetup meetup = result.get();
model.addAttribute("title", meetup.getMeetupName() + " Details");
model.addAttribute("meetups", meetup);
model.addAttribute("trails", trailRepository.findAll());
}
return "meetups/details";
}

Page in my project doesn't work (Tomcat Error)

My page doesn’t open. On this page I can create a user and give him a username and password + role (admin or user). Why does page doesn t work. You can look at the code, it seems to have written correctly. Maybe somewhere I made a mistake in the code.Tomcat gives error 404. I just need him to open this page, you can see the controller
Admin Controller
#Controller
#RequestMapping("/admin")
public class AdminController {
#Autowired
private StudentService studentService;
#GetMapping("/allStudentsAdmin")
public ModelAndView allStudentsForUser() {
ModelAndView mv = new ModelAndView();
List<Student> studentList = studentService.getAllStudents();
mv.addObject("studentList", studentList);
mv.setViewName("allStudentsAdmin");
return mv;
}
#GetMapping(value = "/deleteStudent/{id}")
public ModelAndView deleteUserById(#PathVariable Long id) {
studentService.deleteStudentById(id);
ModelAndView mv = new ModelAndView("redirect:/admin/allStudentsAdmin");
return mv;
}
#GetMapping(value = "/editStudent/{id}")
public ModelAndView displayEditUserForm(#PathVariable Long id) {
ModelAndView mv = new ModelAndView("adminEditStudent");
Student student = studentService.getStudentById(id);
mv.addObject("headerMessage", "Редактирование студента");
mv.addObject("student", student);
return mv;
}
#PostMapping(value = "/editStudent")
public String saveEditedUser(
#RequestParam("id") Long id,
#RequestParam("name") String name,
#RequestParam("surname") String surname,
#RequestParam("avatar") MultipartFile file) {
try {
studentService.updateStudent(name, surname, file, studentService.getStudentById(id));
} catch (FileSystemException ex) {
ex.printStackTrace();
} catch (IOException e) {
return "redirect:/errors";
}
return "redirect:/admin/allStudentsAdmin";
}
#GetMapping(value = "/addStudentAdmin")
public ModelAndView displayNewUserForm() {
ModelAndView mv = new ModelAndView("addStudentAdmin");
mv.addObject("headerMessage", "Add Student Details");
mv.addObject("student", new Student());
return mv;
}
#PostMapping(value = "/addStudentAdmin")
public String saveNewStudent(#RequestParam("name") #NonNull String name,
#RequestParam("surname") #NonNull String surname,
#RequestParam("avatar") MultipartFile file)
throws IOException {
Student student = new Student();
student.setSurname(surname);
student.setName(name);
if (file != null && !file.isEmpty()) {
student.setAvatar(studentService.saveAvatarImage(file).getName());
}
studentService.saveStudent(student);
return "redirect:/admin/allStudentsAdmin";
}
#GetMapping(value = "/addUser")
public ModelAndView displayAddUserForm() {
ModelAndView mv = new ModelAndView("addStudentAdmin");
mv.addObject("headerMessage", "Add Student Details");
mv.addObject("student", new Student());
return mv;
}
#PostMapping(value = "/addUser")
public String saveNewUser(#RequestParam("name") #NonNull String name,
#RequestParam("surname") #NonNull String surname,
#RequestParam("role") #NonNull String role)
throws IOException {
Student student = new Student();
student.setSurname(surname);
student.setName(name);
studentService.saveStudent(student);
return "redirect:/admin/allStudentsAdmin";
}
}
Admin Decorator
<body>
<div id="container">
<div id="header">
</div>
<div id="nav">
<ul>
<li><span>Главная</span></li>
<li class="dropdown"><span>Студенты</span>
<ul>
<li><span>Список студентов</span></li>
<sec:authorize access="hasRole('ADMIN') || hasRole('USER')">
<li><span>Добавить студента</span></li>
</sec:authorize>
<sec:authorize access="hasRole('ADMIN')">
<li><span>Добавить юзера</span></li>
</sec:authorize>
</ul>
</li>
<li><a><span>О нас </span></a></li>
<sec:authorize access="!isAuthenticated()">
<li><span>Выйти</span></li>
</sec:authorize>
</ul>
</div>
</div>
<sitemesh:write property='body'/>
<jsp:include page="/WEB-INF/template/admintemplate.jsp"/>
</body>
</html>
AddUser.JSP
<%#page contentType="text/html" pageEncoding="UTF-8"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<%# taglib prefix="form" uri="http://www.springframework.org/tags/form"%>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.4.0/css/bootstrap.min.css">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.4.0/js/bootstrap.min.js"></script>
<title>Home</title>
</head>
<body>
<div class="add">
<br>
<br>
<br>
<br>
<center>
<h1>${headerMessage}</h1>
<form:form method="POST" action="${pageContext.request.contextPath}/admin/addUser" enctype="multipart/form-data">
<table>
<tr>
<td><label path="Name">Name</label></td>
<td><input type="text" name="name"/></td>
</tr>
<tr>
<td><label path="Surname">Surname</label></td>
<td><input type="text" name="surname"/></td>
</tr>
<tr>
<td><select name="select" size="3" multiple>
<option selected value="s1">Admin</option>
<option value="s2">User</option>
</select></td>
<td>
<input type="text" name="Role"/>
</td>
</tr>
<tr>
<td><input class="btn btn-primary" type="submit" value="Добавить"></td>
</tr>
</table>
</form:form>
</center>
</div>
</body>
</html>
Change URL to admin/addUser
because in your controller you have added a root level admin
#RequestMapping("/admin")
ex .http://localhost:8080/SchoolMaven/admin/addUser

Load dynamic image from external url in thymleaf img tag[SringBoot]

I have a Dynamic external url that i am setting in model at controller side and trying to access in html using thymleaf tag
Here is the code:
Controller:
#RequestMapping(value = "/{id:.+}", method = RequestMethod.GET)
public String searchUser(#PathVariable("id") String data, Model model) {
/*
* if (!data.startsWith("#")) { data = "#" + data; }
*/
List<User> list = userService.searchUserUsingText(data);
if (list.isEmpty()) {
System.out.println("error");
return "404";
} else {
User user = list.get(0);
if (null != user.getName())
model.addAttribute("name", user.getName());
if (null != user.getProfession())
model.addAttribute("profession", user.getProfession());
if (null != user.getPhotoUrl()) {
System.out.println("inside image" + user.getPhotoUrl());
model.addAttribute("image" + user.getPhotoUrl());
}
return "profile";
}
}
PhotoUrl will be a external url like:
https://firebasestorage.googleapis.com/v0/b/mysocialhandle-ecfc0.appspot.com/o/images%2FFtX4VVciacM1jKdrP2NfInSyWMf1%2FFtX4VVciacM1jKdrP2NfInSyWMf1.jpg?alt=media&token=10e06c9b-044e-4e15-ab74-a55429bcb22b
Thymleaf/Html side:
<div class="container">
<div class="owner">
<div class="avatar">
<img th:src="#{${image}}" alt="Circle Image"
class="img-circle img-no-padding img-responsive">
</div>
<div class="name">
<h4 class="title" th:text="${name}">
<br />
</h4>
<h6 class="description" th:text="${profession}"></h6>
</div>
</div>
name and profession are resolved perfectly but at img Tag i am getting null.
Guys please help in this...
You have
model.addAttribute("image" + user.getPhotoUrl());
I think you meant to have
model.addAttribute("image", user.getPhotoUrl());

Spring Boot multiple controllers with same mapping

My problem is very similar with this one: Spring MVC Multiple Controllers with same #RequestMapping
I'm building simple Human Resources web application with Spring Boot. I have a list of jobs and individual url for each job:
localhost:8080/jobs/1
This page contains job posting details and a form which unauthenticated users -applicants, in this case- can use to apply this job. Authenticated users -HR Manager-, can see only posting details, not the form. I have trouble with validating form inputs.
What I tried first:
#Controller
public class ApplicationController {
private final AppService appService;
#Autowired
public ApplicationController(AppService appService) {
this.appService = appService;
}
#RequestMapping(value = "/jobs/{id}", method = RequestMethod.POST)
public String handleApplyForm(#PathVariable Long id, #Valid #ModelAttribute("form") ApplyForm form, BindingResult bindingResult) {
if (bindingResult.hasErrors()) {
return "job_detail"; //HTML page which contains job details and the application form
}
appService.apply(form, id);
return "redirect:/jobs";
}
#RequestMapping(value = "/applications/{id}", method = RequestMethod.GET)
public ModelAndView getApplicationPage(#PathVariable Long id) {
if (null == appService.getAppById(id)) {
throw new NoSuchElementException(String.format("Application=%s not found", id));
} else {
return new ModelAndView("application_detail", "app", appService.getAppById(id));
}
}
}
As you guess this didn't work because I couldn't get the models. So I put handleApplyForm() to JobController and changed a little bit:
#Controller
public class JobController {
private final JobService jobService;
private final AppService appService;
#Autowired
public JobController(JobService jobService, AppService appService) {
this.jobService = jobService;
this.appService = appService;
}
#RequestMapping(value = "/jobs/{id}", method = RequestMethod.POST)
public ModelAndView handleApplyForm(#PathVariable Long id, #Valid #ModelAttribute("form") ApplyForm form, BindingResult bindingResult) {
if (bindingResult.hasErrors()) {
return getJobPage(id);
}
appService.apply(form, id);
return new ModelAndView("redirect:/jobs");
}
#RequestMapping(value = "/jobs/{id}", method = RequestMethod.GET)
public ModelAndView getJobPage(#PathVariable Long id) {
Map<String, Object> model = new HashMap<String, Object>();
if (null == jobService.getJobById(id)) {
throw new NoSuchElementException(String.format("Job=%s not found", id));
} else {
model.put("job", jobService.getJobById(id));
model.put("form", new ApplyForm());
}
return new ModelAndView("job_detail", model);
}
}
With this way, validations works but I still can't get the same effect here as it refreshes the page so that all valid inputs disappear and error messages don't appear.
By the way, job_detail.html is like this:
<h1>Job Details</h1>
<p th:inline="text"><strong>Title:</strong> [[${job.title}]]</p>
<p th:inline="text"><strong>Description:</strong> [[${job.description}]]</p>
<p th:inline="text"><strong>Number of people to hire:</strong> [[${job.numPeopleToHire}]]</p>
<p th:inline="text"><strong>Last application date:</strong> [[${job.lastDate}]]</p>
<div sec:authorize="isAuthenticated()">
<form th:action="#{/jobs/} + ${job.id}" method="post">
<input type="submit" value="Delete this posting" name="delete" />
</form>
</div>
<div sec:authorize="isAnonymous()">
<h1>Application Form</h1>
<form action="#" th:action="#{/jobs/} + ${job.id}" method="post">
<div>
<label>First name</label>
<input type="text" name="firstName" th:value="${form.firstName}" />
<td th:if="${#fields.hasErrors('form.firstName')}" th:errors="${form.firstName}"></td>
</div>
<!-- and other input fields -->
<input type="submit" value="Submit" name="apply" /> <input type="reset" value="Reset" />
</form>
</div>
Check thymeleaf documentation here
Values for th:field attributes must be selection expressions (*{...}),
Also ApplyForm is exposed then you can catch it in the form.
Then your form should looks like this:
<form action="#" th:action="#{/jobs/} + ${job.id}" th:object="${applyForm}" method="post">
<div>
<label>First name</label>
<input type="text" name="firstName" th:value="*{firstName}" />
<td th:if="${#fields.hasErrors('firstName')}" th:errors="*{firstName}"></td>
</div>
<!-- and other input fields -->
<input type="submit" value="Submit" name="apply" /> <input type="reset" value="Reset" />
</form>

Resources