facebook integration via Spring-Social - java

I try to configure facebook integration. But i did't recive accesToken properly. I recieved null. Logger show me variables AccesToken and UserID and it null.
so here my config.
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd">
<bean
class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter">
<property name="customArgumentResolver" ref="facebookWebArgResolver" />
</bean>
<bean id="facebookWebArgResolver"
class="org.springframework.social.facebook.FacebookWebArgumentResolver">
<constructor-arg name="apiKey" value="${facebook.appId}"/>
</bean>
</beans>
And this is my callback controller with FacebookProvider and jsp page.
#Controller
public class SocialTutorial {
private static final Logger LOG = Logger.getLogger(SocialTutorial.class);
#Autowired
FacebookProvider facebookProvider;
#RequestMapping(value = "/connect/facebook", method = RequestMethod.POST)
public String connectAccountToFacebook(#FacebookAccessToken String accessToken, #FacebookUserId String facebookUserId) {
LOG.error("HERE facebook authnticate:" + accessToken + " And user id:" + facebookUserId);
return "redirect:/pages/social.jsp";
}
}
Provider
#Repository("facebookProvider")
public class FacebookProvider {
#Value("${facebook.appId}")
private String apiKey;// = "240362226072898";
#Value("${facebook.appSecret}")
private String appSecret;// = " ";
public String getApiKey() {
return apiKey;
}
public void setApiKey(String apiKey) {
this.apiKey = apiKey;
}
public String getAppSecret() {
return appSecret;
}
public void setAppSecret(String appSecret) {
this.appSecret = appSecret;
}
public FacebookTemplate createTemplate(String accesToken) {
return new FacebookTemplate(accesToken);
}
}
JSP page
<%# taglib uri="http://www.springframework.org/tags/form" prefix="form"%>
<%# taglib prefix='c' uri='http://java.sun.com/jstl/core_rt'%>
<%# taglib prefix="sec"
uri="http://www.springframework.org/security/tags"%>
<%# taglib
uri="http://www.springframework.org/spring-social/facebook/tags"
prefix="facebook"%>
<%# page contentType="text/html;charset=UTF-8" language="java"%>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Update Status</title>
<script
src="http://ajax.googleapis.com/ajax/libs/jquery/1.3/jquery.min.js"
type="text/javascript"></script>
</head>
<body>
Logout
<h2>Services</h2>
<!-- FACEBOOK -->
<c:if test="${connectedToFacebook}">
Connected to Facebook as <c:out
value="${facebookProfile.firstName }" />
<c:out value="${facebookProfile.lastName }" />
</c:if>
<c:if test="${!connectedToFacebook}">
<%/* Connect to Facebook */ %>
<form id="fb_signin" action="<c:url value="/connect/facebook" />"
method="post">
<div class="formInfo"></div>
<div id="fb-root"></div>
<p>
<fb:login-button perms="email,publish_stream,offline_access"
onlogin="$('#fb_signin').submit();" v="2" length="long">Connect to Facebook</fb:login-button>
</p>
</form>
<facebook:init />
</c:if>
<br />
</body>
</html>

Try this. It should work for you:
FacebookConnectionFactory connectionFactory =
new FacebookConnectionFactory("clientId", "clientSecret");
OAuth2Operations oauthOperations = connectionFactory.getOAuthOperations();
OAuth2Parameters params = new OAuth2Parameters();
params.setRedirectUri("https://my-callback-url");
String authorizeUrl = oauthOperations.buildAuthorizeUrl(GrantType.AUTHORIZATION_CODE, params);
response.sendRedirect(authorizeUrl);
// upon receiving the callback from the provider:
AccessGrant accessGrant = oauthOperations.exchangeForAccess(authorizationCode, "https://my-callback-url", null);
Connection<Facebook> connection = connectionFactory.createConnection(accessGrant);
For more information try this.

Related

javax.servlet.jsp.JspTagException: Don't know how to iterate over supplied "items" in <forEach&gt

What I am want to do is to add a record to a table and then to display that newly added record in a jsp page.
Here is what I tried:
Controller:
#Controller
public class UserController {
#Autowired
UserRepository userRepo;
#RequestMapping("/adduser")
public String userform(Model m){
m.addAttribute("command", new Users());
return "adduser";
}
#RequestMapping("/saveuser")
public String save(#ModelAttribute("user") Users user,Model model){
userRepo.save(user);
model.addAttribute("user", user);
return "forward:/user";
}
#RequestMapping("/user")
public String user(Model model) {
return "user";
}
And the jsp page:
<%# page language="java" contentType="text/html; charset=ISO-8859-1"
pageEncoding="ISO-8859-1"%>
<!DOCTYPE html>
<%# taglib prefix="spring" uri="http://www.springframework.org/tags"%>
<%# taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<html lang="en">
<head>
<link rel="stylesheet" type="text/css"
href="webjars/bootstrap/3.3.7/css/bootstrap.min.css" />
<c:url value="/css/main.css" var="jstlCss" />
<link href="${jstlCss}" rel="stylesheet" />
</head>
<body>
<div class="container">
<div class="starter-template">
<h1>Product List</h1>
<table
class="table table-striped table-hover table-condensed table-bordered">
<tr>
<th>Id</th>
<th>Color</th>
<th>Gender</th>
<th>Category</th>
</tr>
<c:forEach var="u" items="${user}">
<tr>
<td>${u.userid}</td>
<td>${u.username}</td>
<td>${u.userphone}</td>
<td>${u.useremail}</td>
</tr>
</c:forEach>
</table>
</div>
</div>
<script type="text/javascript"
src="webjars/bootstrap/3.3.7/js/bootstrap.min.js"></script>
</body>
</html>
Upon running the code the record is getting added successfully but It is not getting displayed instead I am getting the error mentioned in the title.
What to do to make it work?
#RequestMapping("/user")
public List<User> user(Model model) {
...
return ...;
}
${user} is the result of that method user.
<c:forEach var="u" items="${user}">
The forEach tag requires as itemssomething Iterable.
In fact the name should have been plural: users.
You need something like
public class User {
int userid;
String username;
String userphone;
String useremail;
}
<td>${u.userid}</td>
<td>${u.username}</td>
<td>${u.userphone}</td>
<td>${u.useremail}</td>

Why can't I retrieve an attribute from the Model but I'm able to from JSP?

I'm learning spring mvc and understand the use of the Model and ModelAttribute. However, I can't retrieve the Model's attribute so I resorted to using the JSP param value. What am I doing wrong? I checked the model still had a value for the attribute using #ModelAttribute("username") User user / user.username and sure enough it does.
Controller
package login.user;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
#Controller
public class LoginUser {
#RequestMapping("/")
public String showMenu()
{
return "menu";
}
#RequestMapping("login")
public String loginUser(Model model)
{
User newUser = new User();
model.addAttribute("user", newUser);
return "login-user";
}
#RequestMapping("processUser")
public String processUser(Model model)
{
Option newOption = new Option();
model.addAttribute("option", newOption);
return "process-login";
}
}
User
package login.user;
public class User {
private String username;
private char password[];
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public char[] getPassword() {
return password;
}
public void setPassword(char[] password) {
this.password = password;
}
}
login-user.jsp
<%# page language="java" contentType="text/html; charset=ISO-8859-1"
pageEncoding="ISO-8859-1"%>
<%#taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<%# taglib prefix="form" uri="http://www.springframework.org/tags/form"%>
<!DOCTYPE html>
<html>
<head>
<link href="<c:url value="/resources/css/style.css" />" rel="stylesheet" type="text/css" />
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Login User</title>
</head>
<body>
<div>
<form:form action="processUser" modelAttribute="user">
<table>
<tr>
<td>Username:</td>
<td>
<form:input path="username" />
</td>
</tr>
<tr>
<td>Password:</td>
<td>
<form:input type="password" path="password" />
</td>
</tr>
<tr>
<td>
<input type="submit" name="Login" />
</td>
</tr>
</table>
</form:form>
</div>
</body>
</html>
process-login.jsp
<%# page language="java" contentType="text/html; charset=ISO-8859-1"
pageEncoding="ISO-8859-1"%>
<%#taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<%# taglib prefix="form" uri="http://www.springframework.org/tags/form"%>
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Insert title here</title>
</head>
<body>
<form:form modelAttribute="option">
<h3>Welcome ${param.username}. Please choose an activity below</h3> <---- changed from ${user.username}
<div>
<form:select path="option">
<form:option value="Email" label="Email"></form:option>
<form:option value="Enter Recipe" label="Enter Recipe"></form:option>
<form:option value="Retrieve Recipe" label="Retrieve Recipe"></form:option>
</form:select>
</div>
</form:form>
</body>
</html>
Just change your last #RequestMapping method as follows:
#RequestMapping("processUser")
public String processUser(#ModelAttribute("user") User user, Model model)
{
Option newOption = new Option();
model.addAttribute("user", user);
model.addAttribute("option", newOption);
return "process-login";
}
Now use ${user.username} in jsp.
The spring model data is stored in the standard Java request scope. If you are trying to get the username, you need to add it in the request scope again. So, you can write the processUser method as follows.
#RequestMapping("processUser")
public String processUser(#ModelAttribute("user") User user,Model model)
{
Option newOption = new Option();
// do stuff with user data
newOption.setUsername(user.getUsername());
model.addAttribute("option", newOption);
return "process-login";
}
So, you should be able to get it in the jsp as ${option.username}.

Controller load error message after load and not after submit

Try to figure out when I load my jsp page the error message is shown even if I do not submit the button. Can anyone advice how to show error message after submit the button. I post my code here for control.
Thanks in advance
LoginController
#Controller
//#RequestMapping("/")
public class LoginController {
#Autowired
private LoginService loginServiceImpl;
#RequestMapping(value="/login", method = { RequestMethod.GET, RequestMethod.POST })
public ModelAndView validUser(#ModelAttribute("person") PersonModel personModel) {
ModelAndView model= new ModelAndView("login");
try
{
boolean validUser = loginServiceImpl.isValidUser(personModel.getName(), personModel.getPassword());
//Zjistí zda-li je user přihlášen
if(validUser)
{
System.out.println("User Login Successful");
model.addObject("successMessage", personModel.getName());
}
else
{
System.out.println("Login wasn't Successful");
model.addObject("unsuccessmessage", "Invalid credentials!!");
}
}
catch(Exception e)
{
e.printStackTrace();
}
return model;
}
}
JSP Page
<%#taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<%# page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%# taglib prefix="form" uri="http://www.springframework.org/tags/form" %>
<html>
<head>
<title>Login Page</title>
</head>
<body>
<form:form id="loginForm" method="post" action="login" modelAttribute="person">
<form:label path="name">Login name:</form:label>
<form:input id="name" name="name" path="name" /><br>
<form:label path="password">Password</form:label>
<form:password id="password" name="password" path="password" /><br>
<input type="submit" value="Submit" />
<h2>${unsuccessMessage}</h2>
<h2>${successMessage}</h2>
</form:form>
</body>
</html>

How do I reset a ModelAttribute in Spring 3?

I just started with Spring MVC so it's probably a rookie mistake.
The ModelAttribute is reused every request. How can I make sure every POST starts with a clean object?
My controller (MyController.java):
#Controller
public class MyController {
#RequestMapping(method = RequestMethod.POST)
public String processChoice(#ModelAttribute("myData") MyData myData, BindingResult bindingResult) {
System.out.println("POST: myData = " + myData);
return "redirect:/myview?choice=" + myData.getChoice();
}
#RequestMapping(method = RequestMethod.GET)
public String displayChoice(#RequestParam(required = false) String choice, Model model) {
System.out.println("GET: Choice = " + choice);
model.addAttribute("myData", new MyData(choice));
return "myview";
}
}
My view (myview.jsp):
<%# page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%# taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%# taglib prefix="form" uri="http://www.springframework.org/tags/form" %>
<!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=UTF-8">
<title>Spring Tests</title>
</head>
<body>
<form:form modelAttribute="myData" method="POST">
<form:select path="choice">
<option></option>
<option value="one">One</option>
<option value="two">Two</option>
</form:select>
<input type="submit" value="Choose"/>
</form:form>
<c:if test="${not empty myData.choice}">Choice = ${myData.choice}</c:if>
<c:if test="${empty myData.choice}">No choice</c:if>
</body>
</html>
Successive clicks on the "Choose" button appends the chosen values instead of just POST-ing the current one:
GET: Choice = null
POST: myData = MyData [choice=two]
GET: Choice = two
POST: myData = MyData [choice=two,one]
GET: Choice = two,one
POST: myData = MyData [choice=two,one,]
GET: Choice = two,one,
POST: myData = MyData [choice=two,one,,one]
GET: Choice = two,one,,one
Add this into your controller:
#ModelAttribute("myData")
public MyData getMyData() {
return new MyData();
}

Spring MVC and form binding : how to remove an item from a List?

I have a Person model attribute that contains a list of emails.
I've created some JavaScript code that deletes elements from an HTML list of emails. This is pure JavaScript client side code, no AJAX call.
After submitting, I don't understand why I get all the emails in the corresponding #Controller method, even the ones that were deleted in the HTML.
Can anyone please explain?
JSP
<%# taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%# taglib prefix="form" uri="http://www.springframework.org/tags/form" %>
<%# taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %>
<%# taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"></meta>
<link rel="stylesheet" href="<c:url value="/styles/resume.css"/>" type="text/css"></link>
<link href="http://ajax.googleapis.com/ajax/libs/jqueryui/1.8/themes/base/jquery-ui.css" rel="stylesheet" type="text/css"></link>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.8/jquery.min.js"></script>
<script src="http://ajax.googleapis.com/ajax/libs/jqueryui/1.8/jquery-ui.min.js"></script>
<script src="/resume/js/jquery.editable-1.0.1.js"></script>
<title>Resumes manager</title>
<script>
$(document).ready(function() {
$('.trash').click(function() {
$(this.parentNode).remove();
});
});
</script>
</head>
<body>
<h1>Personal data</h1>
<form:form modelAttribute="person" action="/resume/person/edit/save" id="personForm" method="post" >
<table>
<tr>
<td>Email addresses:</td>
<td colspan="4">
<ol id="emails">
<c:forEach items="${person.emails}" varStatus="status">
<li><form:hidden path="emails[${status.index}].order" class="emailsDisplayOrder"></form:hidden><form:input path="emails[${status.index}].label"></form:input><form:input type="email" path="emails[${status.index}].value"></form:input><input type="image" src="/resume/images/trash.png" class="trash" value="${status.index}"></input></li>
</c:forEach>
</ol>
</td>
</tr>
</table>
</form:form>
</body>
</html>
Controller
#Controller
#SessionAttributes(types={Person.class}, value={"person"})
public class PersonController {
private final static String PERSON_VIEW_NAME = "person-form";
private ResumeManager resumeManager;
#Autowired()
public PersonController(ResumeManager resume) {
this.resumeManager = resume;
}
#InitBinder
public void initBinder(WebDataBinder dataBinder) {
dataBinder.setDisallowedFields("id");
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
dateFormat.setLenient(false);
dataBinder.registerCustomEditor(Date.class, new CustomDateEditor(dateFormat, true));
}
#RequestMapping(value="/person/edit/save")
public String save(#ModelAttribute(value="person") Person p, BindingResult result, SessionStatus status) {
new PersonValidator().validate(p, result);
Collections.sort(p.getEmails()); //this collection still contains client-side dropped objects
this.resumeManager.savePerson(p);
return PERSON_VIEW_NAME;
}
}
Explanation
When you load a page with <form:form modelAttribute="person" ...>, there are two cases :
case 1 : if person doesn't exist, it creates an empty Person
case 2 : if person already exists, it uses it
In all cases, when a page is loaded, there is an existing person.
When you submit a form, Spring MVC updates this existing person only with the submitted information.
So in case 1, if you submit email 1, 2, 3 and 4, Spring MVC will add 4 emails to the empty person. No problem for you in this case.
But in case 2 (for example when you edit an existing person in session), if you submit email 1 and 2, but person has already 4 emails, then Spring MVC will just replace email 1 and 2. Email 3 and 4 still exist.
A possible solution
Probably not the best one, but it should work.
Add a remove boolean to the Email class :
...
public class Email {
...
private boolean remove; // Set this flag to true to indicate that
// you want to remove the person.
...
}
In the save method of your controller, remove the emails that have remove set to true.
Finally, in your JSP, add this hidden field :
<form:hidden path="emails[${status.index}].remove" />
And tell your Javascript to set the input value to true when the user clicks to delete the email.
Alternate solution to Jerome Dalbert one
Jerome's solution should work (thanks again for clear answer and solution), but I didn't want to modify business model.
So here is the way I found out: mark HTML elements to remove using java-script and actually remove it using ajax calls at form submit (I initially avoided ajax to keep model unchanged until user submits, but this solutions preserves that requirement).
JSP:
<%# taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%# taglib prefix="form" uri="http://www.springframework.org/tags/form" %>
<%# taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %>
<%# taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"></meta>
<link rel="stylesheet" href="<c:url value="/styles/resume.css"/>" type="text/css"></link>
<link href="http://ajax.googleapis.com/ajax/libs/jqueryui/1.8/themes/base/jquery-ui.css" rel="stylesheet" type="text/css"></link>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.8/jquery.min.js"></script>
<script src="http://ajax.googleapis.com/ajax/libs/jqueryui/1.8/jquery-ui.min.js"></script>
<script src="/resume/js/jquery.editable-1.0.1.js"></script>
<title>Resumes manager</title>
<script>
$('.sortable').sortable({
update: function(event,ui) {
var liElements = this.getElementsByTagName('li');
$(liElements).each(function(i, liElement) {
var orderElements = liElement.getElementsByClassName('order');
$(orderElements).each(function (j, orderElement) {
orderElement.value = i;
});
});
}
});
$('.trashable').click(function() {
$(this.parentNode.childNodes).each(function(index, element) {
if(element.src.match(/trash.png/) != null) {
element.src = '/resume/images/back.png';
this.parentNode.className = 'trashed';
} else if(element.src.match(/back.png/) != null) {
element.src = '/resume/images/trash.png';
this.parentNode.className = '';
} else {
element.disabled = !element.disabled;
}
});
});
function trash(element) {
var sfx = element.alt;
var lnk = ('/resume/person/edit/').concat(sfx);
$.ajax({
url: lnk
});
}
$('#personForm').submit(function() {
var trashed = $(this).find('.trashed');
$(trashed).each(function(index, element) {
var img = $(element).find('.trashable');
var tmp = $(img)[0];
trash(tmp);
});
});
});
</script>
</head>
<body>
<h1>Personal data</h1>
<form:form modelAttribute="person" action="/resume/person/edit/save" id="personForm" method="post" >
<table>
<tr>
<td>Email addresses:</td>
<td colspan="4">
<ol class="sortable">
<c:forEach items="${person.emails}" varStatus="status">
<li><form:hidden path="emails[${status.index}].order" class="order"></form:hidden><form:input path="emails[${status.index}].label"></form:input><form:input type="email" path="emails[${status.index}].value"></form:input><img src="/resume/images/trash.png" class="trashable" alt="dropEmail/${person.emails[status.index].id}"></img></li>
</c:forEach>
</ol>
</td>
</tr>
<tr><td colspan="5"><form:button name="save" value="${person.id}">${person.id == 0 ? 'save' : 'update'}</form:button></td></tr>
</table>
</form:form>
</body>
</html>
Controller:
#Controller
#SessionAttributes(types={Person.class}, value={"person"})
public class PersonController {
private final static String PERSON_VIEW_NAME = "person-form";
private ResumeManager resumeManager;
#Autowired()
public PersonController(ResumeManager resume) {
this.resumeManager = resume;
}
#InitBinder
public void initBinder(WebDataBinder dataBinder) {
dataBinder.setDisallowedFields("id");
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
dateFormat.setLenient(false);
dataBinder.registerCustomEditor(Date.class, new CustomDateEditor(dateFormat, true));
}
#RequestMapping(value="/person/edit/{id}")
public String edit(#PathVariable("id") long personId, Model model) {
Person p = this.resumeManager.getPersonById(personId);
if(p != null) {
model.addAttribute("person", p);
return PERSON_VIEW_NAME;
} else {
return "redirect:/";
}
}
#RequestMapping(value="/person/edit/save")
public String save(#ModelAttribute(value="person") Person p, BindingResult result, SessionStatus status) {
new PersonValidator().validate(p, result);
Collections.sort(p.getEmails());
this.resumeManager.savePerson(p);
return PERSON_VIEW_NAME;
}
#RequestMapping(value="/person/edit/dropEmail/{id}")
#ResponseBody
public void dropEmail(#ModelAttribute(value="person") Person p, #PathVariable("id") long id) {
int i = 0;
for(Email e : p.getEmails()) {
if(e.getId() == id) {
p.getEmails().remove(i);
break;
}
i++;
}
}
}

Categories