I am trying to implement facebook based sign in . Everything works however i don't know how to handle the refresh case that is once a user is redirected to the page how and the user clicks on refresh it triggers another request , how do i handle that ?
package com.example.demo.controllers;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.view.RedirectView;
import com.example.demo.FbService.FbService;
#Controller
#RequestMapping("/")
public class FbController {
#Autowired
private FbService facebookService;
#GetMapping("/createFacebookAuthorization")
public RedirectView createFacebookAuthorization(){
return new RedirectView(facebookService.createFacebookAuthorizationURL());
}
#GetMapping("/facebook")
public String createFacebookAccessToken(#RequestParam("code") String code){
String accToken=facebookService.createFacebookAccessToken(code);
Object obj=facebookService.getName(accToken);
return "details";
}
#RequestMapping("/")
public ModelAndView firstPage() {
return new ModelAndView("welcome");
}
}
package com.example.demo.FbService;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.social.facebook.api.Facebook;
import org.springframework.social.facebook.api.impl.FacebookTemplate;
import org.springframework.social.facebook.connect.FacebookConnectionFactory;
import org.springframework.social.oauth2.AccessGrant;
import org.springframework.social.oauth2.OAuth2Operations;
import org.springframework.social.oauth2.OAuth2Parameters;
import org.springframework.stereotype.Service;
#Service
public class FbService {
#Value("${spring.social.facebook.appId}")
String facebookAppId;
#Value("${spring.social.facebook.appSecret}")
String facebookSecret;
public String createFacebookAuthorizationURL(){
FacebookConnectionFactory connectionFactory = new FacebookConnectionFactory(facebookAppId, facebookSecret);
OAuth2Operations oauthOperations = connectionFactory.getOAuthOperations();
OAuth2Parameters params = new OAuth2Parameters();
params.setRedirectUri("http://localhost:8080/facebook");
params.setScope("public_profile,email");
return oauthOperations.buildAuthorizeUrl(params);
}
public String createFacebookAccessToken(String code) {
FacebookConnectionFactory connectionFactory = new FacebookConnectionFactory(facebookAppId, facebookSecret);
AccessGrant accessGrant = connectionFactory.getOAuthOperations().exchangeForAccess(code, "http://localhost:8080/facebook", null);
return accessGrant.getAccessToken();
}
public Object getName(String accessToken) {
Facebook facebook = new FacebookTemplate(accessToken);
String[] fields = {"id", "name","email"};
return facebook.fetchObject("me", String.class, fields);
}
}
details.html
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<title>Login</title>
</head>
<body>
<div style="border: 1px solid #ccc; padding: 5px; margin-bottom: 20px;">
Welcome
</div>
</body>
</html>
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<title>Login</title>
<meta name="description" content="" />
<meta name="viewport" content="width=device-width" />
<base href="/" />
<link rel="stylesheet" type="text/css" href="/webjars/bootstrap/css/bootstrap.min.css" />
<link rel="stylesheet" href="/webjars/font-awesome/css/font-awesome.min.css"></link>
</head>
<body>
<div style="border: 1px solid #ccc; padding: 5px; margin-bottom: 20px;">
Validate using Facebook |
</div>
</body>
</html>
The starting page which sends the request
The redirected page which works fine
The error that appears after refresh is done
I know why it is coming but don't know what would be the solution to prevent it .
Any help would be appreciated .
Related
I'm building a blog app and in this instance I want to create a new post. I created a controller with #GetMapping and #PostMapping with value "/posts/new". I used
th:action = "#{'/posts/new'}" (LINE 14) in thymeleaf but when I start the web app, and access the localhost:8080/posts/new it gives the 404 error that the url is not found, but it is there...I double checked spelling, code...pretty much everything but just can't seem to figure out what mistake did I make. Here is the code:
post_new.html
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Blog :: New Post</title>
</head>
<body>
<div class="container">
<a th:href="#{/}">Home</a>
<form action="#"
th:action="#{'/posts/new'}"
th:object="${post}">
<input type="hidden" th:field="*{account}" />
<input type="hidden" th:field="*{createdAt}" />
<h2>Write new post</h2>
<div>
<label for="new-post-title">Title</label>
<input id="new-post-title" type="text" th:field="*{title}" placeholder="Title"/>
</div>
<div>
<label for="new-post-body">Body</label>
<textarea id="new-post-body" th:field="*{body}"></textarea>
</div>
<button type="submit">Publish post</button>
</form>
</div>
</body>
</html>
PostController.java
package com.hellion.writeup.controller;
import com.hellion.writeup.models.Account;
import com.hellion.writeup.models.Post;
import com.hellion.writeup.service.AccountService;
import com.hellion.writeup.service.PostService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import java.util.Optional;
#Controller
public class PostController {
#Autowired
private PostService postService;
#Autowired
private AccountService accountService;
#GetMapping("/posts/{id}")
public String getPost(#PathVariable Long id, Model model) {
Post post = postService.getPost(id, model);
if (post != null) {
model.addAttribute("post", post);
return "post";
} else {
return "404";
}
}
#GetMapping("/posts/new")
public String createNewPost(Model model){
return postService.createNewPost(model);
}
#PostMapping("/posts/new")
public String saveNewPost(#ModelAttribute Post post){
postService.save(post);
return "redirect:/posts/" + post.getId();
}
}
PostService.java
package com.hellion.writeup.service;
import com.hellion.writeup.models.Account;
import com.hellion.writeup.models.Post;
import com.hellion.writeup.repository.PostRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.ui.Model;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Optional;
#Service
public class PostService {
#Autowired
private PostRepository postRepository;
#Autowired
private AccountService accountService;;
public Optional<Post> getById(Long id) {
return postRepository.findById(id);
}
public List<Post> getAll() {
return postRepository.findAll();
}
public Post save(Post post) {
if (post.getId() == null) {
post.setCreatedAt(LocalDateTime.now());
}
return postRepository.save(post);
}
public Post getPost(Long id, Model model) {
Optional<Post> optionalPost = getById(id);
if (optionalPost.isPresent()) {
Post post = optionalPost.get();
return post;
}
return null;
}
public String createNewPost(Model model){
Optional<Account> optionalAccount = accountService.findByEmail("user.user#domain.com");
if(optionalAccount.isPresent()){
Post post = new Post();
post.setAccount(optionalAccount.get());
model.addAttribute("post", post);
return "post_new";
}else{
return "404";
}
}
}
post.html
<!DOCTYPE HTML>
<html land= "en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE-edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link th:href="#{/styles/style.css}" rel="stylesheet" />
<title>Writeup :: Post</title>
</head>
<body>
<div class ="container">
<a th:href="#{'/'}">Home</a>
<div class="post">
<h2 th:text="${post.title}">Title</h2>
<h5 th:text="'Written by: ' + ${post.account.getFirstName()}">Account First Name</h5>
<h5 th:text="'Created on: ' + ${post.createdAt}">Created At</h5>
<p th:text="${post.body}">Body text</p>
</div>
</div>
</body>
</html>
The GET method for /posts/new invokes the method createNewPost in the service layer. If optionalAccount does not exist, the page 404 is returned. A possible issue is the optionalAccount is empty hence returning 404.
if(optionalAccount.isPresent()) {
Post post = new Post();
post.setAccount(optionalAccount.get());
model.addAttribute("post", post);
return "post_new";
} else {
return "404";
}
The th:action should be th:action="#{/posts/new}".
I found the solution...So basically, I got stackoverflow error and the solution to that is, because I was using Lombok and #Data annotation in my "model" package, the #Data was causing some bugs and by changing it to #Getter and #Setter the issue was fixed.
I understand how to return a string from my controller as demonstrated here
I could modify this to take a text value from a html form.
However, when i try to retrieve number 'salary' from my form, it gives me an error of "There was an unexpected error (type=Not Found, status=404)." What needs to be fixed?
here is my ServingWebContent.java
package com.example.servingwebcontent;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
#SpringBootApplication
public class ServingWebContentApplication {
public static void main(String[] args) {
SpringApplication.run(ServingWebContentApplication.class, args);
}
}
here is BudgetingController.java
package com.example.servingwebcontent;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
#Controller
public class BudgetingController {
#GetMapping("/greeting")
public String greeting(#RequestParam(name="name", required=false, defaultValue="World") String name, Model model) {
model.addAttribute("name", name);
return "greeting";
}
#GetMapping("/results")
public int results(#RequestParam(name="salary", required=true) int salary, Model model) {
model.addAttribute("salary", salary);
return salary;
}
}
here is index.html
<!DOCTYPE HTML>
<html xmlns:th="http://www.thymeleaf.org"></html>
<head>
<title>Budgeting Tool</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
</head>
<body>
<form action="/results.html" method="GET">
<div>
<header>
<h3><strong>Monthly Income</strong></h3>
</header></div>
<div>
<label>Monthly Salary:</label>
<input type="number" name="salary" min="0" required>
</div>
<!--- Submits to results.html --->
<input type="submit" value="Submit">
</form>
</body>
</html>
And finally, here is results.html
<!DOCTYPE HTML>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<title>Results</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
</head>
<body>
<p th:text=" ${salary} " />
</body>
</html>
The normal form submission method is POST.
This case logic is View->Controller->View. I guess this example from https://spring.io/. So this contact path is "/". You can change index.html and BudgetingController.java as below.
I am trying to create a simple spring MVC app in Scala I did define my methods in the controller to bring back html pages based on name from resources folder but it just always brings back just index page and the rest of html pages while trying to access the route it just fails, but same application works fine in Java.
full source code is here:-
Java:-
https://github.com/kali786516/SpringConfigServer-client/tree/master/src/main/java/com/example/SpringConfigServerclient
Scala:-
https://github.com/kali786516/SpringConfigServer-client/tree/master/src/main/scala/com/ps/spring/mvc/psbankapp
Error in Scala:-
Index html Works Fine:-
but rest of the routes doesn't work in scala
Scala controller:-
package com.ps.spring.mvc.psbankapp.controllers
import org.springframework.beans.factory.annotation.Value
import org.springframework.cloud.context.config.annotation.RefreshScope
import org.springframework.stereotype.Controller
import org.springframework.ui.Model
import org.springframework.web.bind.annotation.RequestMapping
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.web.bind.annotation.RequestMethod
//#RefreshScope
#Controller
//#ComponentScan(basePackages = Array("com.ps.spring.mvc.psbankapp"))
class AccountController {
#RequestMapping(value = Array("/"))
def showHomePage(): Unit = {
"index"
}
#RequestMapping(value = Array("/new"), method = Array(RequestMethod.GET))
def newAccount(): Unit = {
"newAccount"
}
#RequestMapping(value = Array("/showAccount"))
def showAccount(): Unit = {
"showAccount"
}
}
Java Controller:-
package com.example.SpringConfigServerclient;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMethod;
#RefreshScope
#Controller
public class RateController {
#RequestMapping(value = "/index",method = RequestMethod.GET)
public String getIndex() {
return "index";
}
#RequestMapping(value = "/new",method = RequestMethod.GET)
public String newAccount() {
return "newAccount";
}
#RequestMapping(value = "/showAccount",method = RequestMethod.GET)
public String showAccount() {
return "showAccount";
}
}
Finally got it working by adding below context in my HTML files.
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:th="http://www.thymeleaf.org"
xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-springsecurity3"
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout">
<head>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
Answer:-
Error resolving template "index", template might not exist or might not be accessible by any of the configured Template Resolvers
full html if you need:-
<!DOCTYPE HTML>
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:th="http://www.thymeleaf.org"
xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-springsecurity3"
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout">
<head>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<title>Pluralsight Training: Config Client</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<!-- Latest compiled and minified CSS -->
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous"></link>
</head>
<body>
<div class="row">
<div class="col-md-2"></div>
<div class="col-md-8">
<h1>Pluralsight Training: Welcome to PS Bank Web Application index</h1>
</div>
<div class="col-md-2"></div>
</div>
</body>
</html>
I'm trying to learn thymeleaf deeper and facing a problem, that after a post method nothing appears in my other page. I've watched tutorials and docs, but seems I`m missing something.
So first of all I have main page with MainController:
package com.gallery.galleryproject.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
#Controller
public class MainController {
#RequestMapping(value = "", method = RequestMethod.GET)
public String loadMainPage() {
return "main.html";
}
}
<!doctype html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<meta name="viewport"
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Welcome</title>
</head>
<body style="background-color: #D3D3D3">
<nav>
<div>
<h2 style="text-align: center">Welcome to gallery</h2>
</div>
</nav>
<section style="padding-top: 20px">
<div style="text-align: center;">
<p>View gallery: Visit</p>
<p>Add new photo to gallery: Visit</p>
</div>
</section>
</body>
</html>
Then I have a gallery controller and gallery page(in this page i want display information which was sent from photo page). GalleryController + page
package com.gallery.galleryproject.controller;
import com.gallery.galleryproject.model.Photo;
import com.gallery.galleryproject.service.GalleryService;
import com.gallery.galleryproject.service.PhotoService;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
#Controller
public class GalleryController {
private GalleryService galleryService;
public GalleryController(GalleryService galleryService) {
this.galleryService = galleryService;
}
#RequestMapping(value = "/gallery", method = RequestMethod.GET)
public String listOfObjects(Model model) {
Photo photo = galleryService.getAllPhotos();
model.addAttribute("photo", photo);
return "gallery.html";
}
}
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Gallery</title>
</head>
<body>
<nav>
<div>
<h2 style="text-align: center">Take a look..</h2>
<!-- TODO: implement here with thymeleaf for loop printing all photo objects received from backend -->
</div>
</nav>
<section>
<div class="container">
<div class="display-galery" style="padding-left: 30px">
<p>Id of the photo: <i th:text="${photo.id}"></i></p>
<p>Name of the photo: <i th:text="${photo.name}"></i></p>
<p>Tag of the photo: <i th:text="${photo.tag}"></i></p>
<p>Quality of the photo: <i th:text="${photo.quality}"></i></p></div>
</div>
</section>
</body>
</html>
Here's my photo controller + html page where i fill up the form.
package com.gallery.galleryproject.controller;
import com.gallery.galleryproject.model.Photo;
import com.gallery.galleryproject.service.PhotoService;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
#Controller
public class PhotoController {
private PhotoService photoService;
public PhotoController(PhotoService photoService){
this.photoService = photoService;
}
#RequestMapping(value = "/photo", method = RequestMethod.GET)
public String displayPhoto(Model model) {
Photo photo = new PhotoService().displayPhotos();
model.addAttribute("photoC", photo);
return "photo";
}
}
<!doctype html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<meta name="viewport"
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Welcome</title>
</head>
<body >
<nav>
<div>
<h2 style="text-align: center">Fill all the fields</h2>
</div>
</nav>
<section>
<form action="#" th:action="#{/gallery}" th:object="${photoC}" method="POST">
<p>Enter ID: </p> <input type="number" th:field="*{id}"><br>
<p>Enter photo name: </p> <input type="text" th:field="*{name}"><br>
<p>Enter photo tag: </p> <input type="text" th:field="*{tag}"><br>
<p>Enter photo quallity:</p> <input type="number" th:field="*{quality}"><br>
<input type="file">
<input type="submit" value="Submit"> <input type="reset" value="Cancel">
</form>
</section>
</body>
</html>
Also I have services: GalleryService which is empty right now(now i'm kinda lost so that's the reason why it's empty) and PhotoService where I use getters to get info
package com.gallery.galleryproject.service;
import com.gallery.galleryproject.controller.GalleryController;
import com.gallery.galleryproject.model.Photo;
import org.springframework.stereotype.Service;
#Service
public class GalleryService {
public Photo getAllPhotos() {
Photo photo = new Photo();
return photo;
}
}
package com.gallery.galleryproject.service;
import com.gallery.galleryproject.model.Photo;
import org.springframework.stereotype.Service;
#Service
public class PhotoService {
public Photo displayPhotos() {
Photo photos = new Photo();
photos.getId();
photos.getName();
photos.getTag();
photos.getQuality();
return photos;
}
}
You dont have ant relevant POST method in your Gallery Controller. You only have a GET mapping for /gallery end point Try adding something like the following to your Gallery Controller.
#RequestMapping(value = "/gallery", method = RequestMethod.POST)
public String savePhoto(Photo photo) {
// Your service method to save photo here
return "xxx.html";
}
I have a JSP that receives a collection list from an action class. I am iterating through that list and I wish to set the values of that list to another object inside another action class through a form request. When I use the displayMovies.jsp when I use the <s:propertytag in the iterator it displays on the different objects in the collection. I want to save or pass each of those objects in the collection to a different action class.
displayMovies.jsp
<%# page language="java" contentType="text/html; charset=ISO-8859-1"
pageEncoding="ISO-8859-1" import="com.sans.model.Movie" %>
<%# taglib prefix="s" uri="/struts-tags"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Insert title here</title>
</head>
<body>
Movie retrieval Page
<br />
<s:iterator value="movieRetrievedArray" var="movieS">
<s:form action="movieDetails.action" method="post" id="movieDetailsForm">
<s:property value="title"/><br />
<s:property value="releaseDate"/><br />
<s:hidden name="movieDetailedInformation.title" value="%{title}" id="hiddenMovie" />
<img src="<s:property value="posterPath" />" onClick="test()">
</s:form>
<br />
<br />
</s:iterator>
<script type="text/javascript">
function test() {
document.getElementById("movieDetailsForm").submit();
}
</script>
</body>
</html>
MovieDetailsActions.java
package com.esi.actions;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import org.apache.struts2.ServletActionContext;
import org.apache.struts2.convention.annotation.Action;
import org.apache.struts2.convention.annotation.Result;
import org.apache.struts2.convention.annotation.Results;
import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ActionSupport;
import com.sans.model.Movie;
#SuppressWarnings("serial")
#Results({
#Result(name="success", location="/RetrieveMovies/movieDetails.jsp"),
#Result(name="input", location="/RetrieveMovies/movieError.jsp")
})
public class MovieDetailsAction extends ActionSupport {
private Movie movieDetailedInformation = new Movie();
#Action(value="movieDetails")
public String execute() {
System.out.println(movieDetailedInformation.getTitle());
return SUCCESS;
}
public Movie getMovieDetailedInformation() {
return movieDetailedInformation;
}
public void setMovieDetailedInformation(Movie movieDetailedInformation) {
this.movieDetailedInformation = movieDetailedInformation;
}
}
You should use status variable on iterator tag.
<s:form action="movieDetails.action" method="post" id="movieDetailsForm">
<s:iterator value="movieRetrievedArray" var="movieS" status="status">
<s:property value="title"/><br />
<s:property value="releaseDate"/><br />
<s:hidden name="movieDetailedInformationList[%{#status.index}].title" value="%{title}" id="hiddenMovie" />
<br />
<br />
</s:iterator>
<img src="<s:property value="posterPath" />" onClick="test()">
</s:form>
The movieDetailedInformationList is
private List<Movie> movieDetailedInformationList;
public List<Movie> getMovieDetailedInformationList() { return movieDetailedInformationList; }
You don't need to initialize movieDetailedInformationList, because Struts2 populate it with parameters from the post request.
The Movie class should be public and have default constructor, the public setter for title is necessary.