I've been trying to solve this issue for a lot of time but I can't see what is wrong in my configuration.
The thing I'm trying to do is to create a new "Metadata" object. This object has the following domain class:
package domain;
import java.util.ArrayList;
import java.util.Collection;
import javax.persistence.Access;
import javax.persistence.AccessType;
import javax.persistence.Entity;
import javax.persistence.ManyToMany;
import javax.validation.Valid;
import javax.validation.constraints.NotNull;
import org.codehaus.jackson.annotate.JsonIgnore;
import org.hibernate.validator.constraints.NotBlank;
#Entity
#Access(AccessType.PROPERTY)
public class Metadata extends DomainEntity{
private String name;
//Relationship
private Collection<Question> questions;
public Metadata() {
super();
questions = new ArrayList<Question>();
}
#Valid
#NotBlank
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
#Valid
#NotNull
#ManyToMany(mappedBy = "metadata")
public Collection<Question> getQuestions() {
return questions;
}
public void setQuestions(Collection<Question> questions) {
this.questions = questions;
}
}
So I have a button that goes to a create page with empty input of property "name" (rest of properties are empty or autogenerated by spring). The view for the creation is the following:
<%#page language="java" contentType="text/html; charset=ISO-8859-1"
pageEncoding="ISO-8859-1"%>
<%#taglib prefix="jstl" uri="http://java.sun.com/jsp/jstl/core"%>
<%#taglib prefix="spring" uri="http://www.springframework.org/tags"%>
<%#taglib prefix="form" uri="http://www.springframework.org/tags/form"%>
<%#taglib prefix="security"
uri="http://www.springframework.org/security/tags"%>
<%#taglib prefix="display" uri="http://displaytag.sf.net"%>
<%# taglib prefix="acme" tagdir="/WEB-INF/tags"%>
<div class="container">
<div class="row">
<div class="col-md-8 col-md-offset-2">
<div class="well well-sm">
<form:form class="form-horizontal" method="POST"
action="metadata/edit.do" modelAttribute="metadata"
enctype="multipart/form-data">
<form:hidden path="id" />
<form:hidden path="version" />
<form:hidden path="questions" />
<fieldset>
<!-- Name -->
<div class="form-group">
<form:label path="name" class="col-md-3 control-label" for="name">
<spring:message code="metadata.name" />
</form:label>
<div class="col-md-6">
<form:input path="name" id="name" name="name" type="text"
class="form-control" />
</div>
<form:errors path="name" cssClass="error" />
</div>
<!-- Form actions -->
<div class="form-group">
<div class="col-md-12 text-center">
<input type="submit" name="save" class="btn btn-primary btn-lg"
value="<spring:message code="metadata.save" />" />
<%-- <jstl:if test="${!create}"> --%>
<!-- <a class="btn btn-primary btn-lg" data-toggle="modal" -->
<%-- data-target="#basicModal"><spring:message --%>
<%-- code="metadata.delete" /></a> --%>
<!-- <div class="modal fade" id="basicModal" tabindex="-1" -->
<!-- role="dialog" aria-labelledby="basicModal" aria-hidden="true"> -->
<!-- <div class="modal-dialog"> -->
<!-- <div class="modal-content"> -->
<!-- <div class="modal-header"> -->
<!-- <button type="button" class="close" data-dismiss="modal" -->
<!-- aria-hidden="true">×</button> -->
<!-- <h4 class="modal-title" id="myModalLabel"> -->
<%-- <spring:message code="metadata.confirm.title" /> --%>
<!-- </h4> -->
<!-- </div> -->
<!-- <div class="modal-body"> -->
<!-- <h3> -->
<%-- <spring:message code="metadata.confirm.body" /> --%>
<!-- </h3> -->
<!-- </div> -->
<!-- <div class="modal-footer"> -->
<!-- <button type="submit" name="delete" class="btn btn-default" -->
<!-- onclick="history.back()"> -->
<%-- <spring:message code="metadata.confirm.yes" /> --%>
<!-- </button> -->
<!-- <button type="button" class="btn btn-primary" -->
<!-- data-dismiss="modal"> -->
<%-- <spring:message code="metadata.confirm.no" /> --%>
<!-- </button> -->
<!-- </div> -->
<!-- </div> -->
<!-- </div> -->
<!-- </div> -->
<%-- </jstl:if> --%>
<a href="metadata/list.do"><input type="button"
class="btn btn-primary btn-lg"
value="<spring:message code="metadata.cancel"/>" id="cancelar"
name="cancelar"
onclick="self.location.href = metadata/list.do" /></a>
</div>
</div>
</fieldset>
</form:form>
</div>
</div>
</div>
</div>
And finally, my controller class, which is failing due to BindingProvider has errors because property "name" of Metadata object cannot be null:
package controllers;
import java.util.ArrayList;
import java.util.Collection;
import javax.validation.Valid;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;
import services.MetadataService;
import domain.Metadata;
import domain.Question;
#Controller
#RequestMapping("/metadata")
public class MetadataController {
// Services ----------------------------------------------------------------
#Autowired
private MetadataService metadataService;
// Constructor
// ---------------------------------------------------------------
public MetadataController() {
super();
}
// Listing
// -------------------------------------------------------------------
#RequestMapping("/list")
public ModelAndView list() {
ModelAndView result;
String uri = "metadata/list";
String requestURI = "metadata/list.do";
Collection<Metadata> metadatas = metadataService.findAll();
result = createListModelAndView(requestURI, metadatas, uri);
return result;
}
// Creation
// ------------------------------------------------------------------
#RequestMapping(value = "/create", method = RequestMethod.GET)
public ModelAndView create() {
ModelAndView result;
Metadata metadata = metadataService.create();
result = createCreateModelAndView(metadata);
return result;
}
// Edition
// -------------------------------------------------------------------
#RequestMapping(value = "/edit", method = RequestMethod.GET)
public ModelAndView edit(#RequestParam int metadataId) {
ModelAndView result;
Metadata metadata = metadataService.findOne(metadataId);
result = createEditModelAndView(metadata);
return result;
}
#RequestMapping(value = "/edit", method = RequestMethod.POST)
public ModelAndView save(#Valid Metadata metadata, BindingResult binding,
RedirectAttributes redirect) {
ModelAndView result;
if (binding.hasErrors()) {
if (metadata.getId() == 0) {
result = createEditModelAndView(metadata, "metadata.commit.error");
} else {
result = createCreateModelAndView(metadata, "metadata.commit.error");
}
} else {
try {
metadataService.save(metadata);
result = new ModelAndView("redirect:list.do");
} catch (Throwable oops) {
if (metadata.getId() == 0) {
result = createEditModelAndView(metadata, "metadata.commit.error");
} else {
result = createCreateModelAndView(metadata, "metadata.commit.error");
}
}
}
return result;
}
// #RequestMapping(value = "/edit", method = RequestMethod.POST, params = "delete")
// public ModelAndView delete(#ModelAttribute Metadata metadata,
// BindingResult bindingResult, RedirectAttributes redirect) {
// ModelAndView result;
//
// try {
// redirect.addFlashAttribute("successMessage", "metadata.deleteSuccess");
// metadataService.delete(metadata);
// result = new ModelAndView("redirect:list.do");
// } catch (Throwable oops) {
// if (oops.getMessage() == "Error") {
// result = createEditModelAndView(metadata, "metadata.error");
// } else {
// result = createEditModelAndView(metadata, "metadata.commit.error");
// }
// }
// return result;
// }
// Other bussiness method
protected ModelAndView createEditModelAndView(Metadata metadata) {
assert metadata != null;
ModelAndView result;
result = createEditModelAndView(metadata, null);
return result;
}
protected ModelAndView createCreateModelAndView(Metadata metadata) {
assert metadata != null;
ModelAndView result;
result = createCreateModelAndView(metadata, null);
return result;
}
protected ModelAndView createEditModelAndView(Metadata metadata,
String message) {
assert metadata != null;
Collection<Question> questions = new ArrayList<Question>();
ModelAndView result;
result = new ModelAndView("metadata/edit");
result.addObject("questions", questions);
result.addObject("metadata", metadata);
return result;
}
protected ModelAndView createCreateModelAndView(Metadata metadata,
String message) {
assert metadata != null;
Collection<Question> questions = new ArrayList<Question>();
ModelAndView result;
result = new ModelAndView("metadata/create");
result.addObject("questions", questions);
result.addObject("create", true);
result.addObject("metadata", metadata);
return result;
}
protected ModelAndView createListModelAndView(String requestURI,
Collection<Metadata> metadatas, String uri) {
ModelAndView result;
result = new ModelAndView(uri);
result.addObject("metadatas", metadatas);
result.addObject("requestURI", requestURI);
return result;
}
}
After looking at this for days, I can not make the submit button to send the values I want to the controller and I don't know what to do. There is no log errors. It just returns to the creation page saying that "name" cannot be null.
public ModelAndView save(#Valid Metadata metadata
i think you are missing #ModelAttribute annotation in the abovve line. you can use it as a
parameter when you want to bind data from the request and add it to the model implicitly.
so change your save method to
public ModelAndView save(#ModelAttribute("metadata") #Valid Metadata metadata
this should work and appereciate if you could post the result.
The problem was that I was using enctype=multipart... while I was not sending any binary data.
That seemed to generate some conflicts in Spring. Removing that enctype and letting Spring use the default setting for it solved the problem.
Related
I have a problem with updatePowerPlant() method, when I try to update powerPlant entity with given id and click the submit button in the update form under localhost:8080/updatePowerPlant adress I get redirected to this url http://localhost:8080/updatePowerPlant/savePowerPlant.
I don't know why. I should get redireted to /powerPlants, wethever entity with given id exists or not, instead /savePowerPlant is added as a last part of a url localhost:8080/updatePowerPlant and I get Request method 'POST' not supported], I know that this is the message I should get afterall there is no GetController with such url but why do I get this weird url? Is it because I use GetController for update?
localhost:8080/updatePowerPlant this I enter in browser to get update form
http://localhost:8080/updatePowerPlant/savePowerPlant this I get when I clik submit in update form
Controller class
#RequiredArgsConstructor
#Controller
public class PowerPlantsController {
private final PowerPlantRepository powerPlantRepository;
private final EventRepository eventRepository;
private final PlantService plantService;
private final EventService eventService;
#GetMapping("form")
public String getForm(Model model) {
model.addAttribute("plant", new PlantViewModel());
return "save";
}
#PostMapping("savePowerPlant")
public String addPowerPlant(#ModelAttribute("plant") #Valid PlantViewModel plant, BindingResult bindingResult) {
if (bindingResult.hasErrors()) {
if (plant.getId() == null) {
return "save";
} else return "updatePowerPlant";
}
if (plant.getId() == null){
plantService.add(plant);
}else {
plantService.update(plant);
}
return "redirect:/powerPlants";
}
#GetMapping("updatePowerPlant/{id}")
public String updatePowerPlant(#PathVariable(value = "id") Integer id, Model model) {
var find = powerPlantRepository.getOne(id);
var plants = plantService.powerPlantToViewModel(find);
model.addAttribute("plant", plants);
return "updatePowerPlant";
}
#ResponseBody
#GetMapping("failures/{id}")
public long failures(#PathVariable("id") int id) {
return eventService.NumberOfFailureEventsForId(id);
}
#ResponseBody
#GetMapping("powerPlants")
public List<PowerPlant> findAll() {
return powerPlantRepository.findAll();
}
#GetMapping("powerPlants/{id}")
public String findById(#PathVariable("id") Integer id, Model model) {
model.addAttribute("plant", powerPlantRepository.getOne(id));
return "plant";
}
#GetMapping("delete/powerPlants")
public String deleteById(#RequestParam(value = "id") Integer id) {
powerPlantRepository.deleteById(id);
return "redirect:/powerPlants";
}
#GetMapping("addEventToPlant")
public String addEventToPlant(#RequestParam(value = "plantId") Long plantId, #RequestParam(value = "eventId")
Long eventId, Model model) {
if (powerPlantRepository.findById(Math.toIntExact(plantId)).isPresent()
&& eventRepository.findById(Math.toIntExact(eventId)).isPresent()) {
var pl = powerPlantRepository.getOne(Math.toIntExact(plantId));
var ev = eventRepository.getOne(Math.toIntExact(eventId));
var eventsForPlant = pl.getEvents();
eventsForPlant.add(ev);
pl.setEvents(eventsForPlant);
powerPlantRepository.save(pl);
}
var t = powerPlantRepository.getOne(Math.toIntExact(plantId)).getEvents();
model.addAttribute("plant", t);
return "plant_events";
}
}
Service class
#org.springframework.stereotype.Service
#RequiredArgsConstructor
public class PlantService implements powerForPowerPlantPerDay, Add, PlantServiceToViewModel {
private final EventRepository eventRepository;
private final PowerPlantRepository powerPlantRepository;
public Map<Integer, String> powerForPowerPlantPerDay(Timestamp date) {
List<Event> list = new ArrayList<>(getAllEvents());
Map<Integer, String> map = new HashMap<>();
list.stream()
.filter(e -> e.startDate.equals(date))
.forEach(e -> map.put(e.id, e.typeOfEvent));
return map;
}
public Collection<Event> getAllEvents() {
return eventRepository.findAll();
}
public void add(PlantViewModel plantViewModel) {
var p = PowerPlant.builder().
name(plantViewModel.getName())
.power(plantViewModel.getPower())
.events(plantViewModel.getListOfEventsForPlant())
.build();
powerPlantRepository.save(p);
}
public PlantViewModel powerPlantToViewModel(PowerPlant powerPlant) {
return PlantViewModel.builder()
.id(powerPlant.getId())
.name(powerPlant.getName())
.power(powerPlant.getPower())
.build();
}
public PowerPlant update(PlantViewModel plantViewModel) {
var plant = powerPlantRepository.getOne(plantViewModel.getId());
plant.setName(plantViewModel.getName());
plant.setPower(plantViewModel.getPower());
return powerPlantRepository.save(plant);
}
}
update html
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.w3.org/1999/xhtml">
<head>
<meta charset="UTF-8">
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css"/>
</head>
<body>
<div class="container">
<h1>Update</h1>
<hr>
<h2>Update powerPlant</h2>
<form action="#" th:action="#{savePowerPlant}" th:object="${plant}" method="POST">
<input id="studentId" th:value="${plant.id}" type="hidden" th:field="*{id}">
<div th:if="${#fields.hasErrors('name')}" th:errors="*{name}">Invalid Name</div>
<input type="text" th:field="*{name}" placeholder="Name" class="form-control mb-4 col-4">
<div th:if="${#fields.hasErrors('power')}" th:errors="*{power}">Invalid power</div>
<input type="text" th:field="*{power}" placeholder="power" class="form-control mb-4 col-4">
<button type="submit" class="btn btn-info col-2">Save</button>
</form>
<hr>
</div>
</body>
</html>
save html
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.w3.org/1999/xhtml">
<head>
<meta charset="UTF-8">
<title>New Student</title>
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css"/>
</head>
<body>
<div class="container">
<h1>Save</h1>
<hr>
<h2>Save powerPlant</h2>
<form action="#" th:action="#{savePowerPlant}" th:object="${plant}" method="POST">
<div th:if="${#fields.hasErrors('name')}" th:errors="*{name}">Invalid Name</div>
<input type="text" th:field="*{name}" placeholder="Name" class="form-control mb-4 col-4">
<div th:if="${#fields.hasErrors('power')}" th:errors="*{power}">Invalid power</div>
<input type="text" th:field="*{power}" placeholder="power" class="form-control mb-4 col-4">
<button type="submit" class="btn btn-info col-2">Save</button>
</form>
<hr>
</div>
</body>
</html>
As you can see here in the documentation you are using relative URLs in your th:action. These get appended to the current URL in the address bar.
So th:action="#{savePowerPlant}" results in current/URL/savePowerPlant.
Simple solution is to switch to absolute URLs either by typing it out completely (http://localhost:portNumber/savePowerPlant) or perhaps even better use server relative URL: th:href="#{~/savePowerPlant}.
I have a question, I didn't understand why this part of the code(where is registration) Spring doesn't find even if I wrote an url. But the same code in another part, for example, add a new book or add the new author of the book is working correctly it added everything into the database and send me into another page. But if I register the person and click submit it always shows me 400 - bad request error. Please help me. What I wrote wrong?
This is my controller(doesn't work registration part with register book (not redirect to registerbook and doesn't add data into DB)):
#Controller
public class HelloController {
private static final Logger logger = Logger.getLogger(HelloController.class.getName());
#Autowired
#Qualifier("author")
private AuthorzDAO authorzDAO;
#Autowired
#Qualifier("book")
private BooksDAO booksDAO;
#Autowired
#Qualifier("borrow")
private BorrowsDAO borrowsDAO;
#Autowired
#Qualifier("person")
private PersonDAO personDAO;
#RequestMapping(value = "/",method = RequestMethod.GET)
public ModelAndView printHello() {
return new ModelAndView("hello", "command", new LoginPerson());
}
#RequestMapping(value = "/",method = RequestMethod.POST)
public String login(#ModelAttribute("SpringWeb")LoginPerson person, ModelMap model, HttpServletRequest request) {
model.addAttribute("info", personDAO.getInfromStudent(person.getEmail(), person.getPassword()));
model.addAttribute("takenbook", person.getEmail());
if (person.getEmail().equals("admin#admin.com") && person.getPassword().equals("admin")) {
logger.warning("AAAAA");
logger.warning(person.getEmail());
return "admin";
} else if(personDAO.checkPerson(person.getEmail(), person.getPassword()) == true){
logger.warning(personDAO.checkPerson(person.getEmail(), person.getPassword()).toString());
logger.warning("BBBBB");
logger.warning(person.getPassword());
return "personinfo";
} else {
return new ResponseStatusException().error();
}
}
#RequestMapping(value = "/registration", method = RequestMethod.GET)
public ModelAndView registration() {
return new ModelAndView("registration", "person", new Person());
}
#RequestMapping(value = "/registration", method = RequestMethod.POST)
public String register(#ModelAttribute("person") Person person) {
logger.warning("Hello");
logger.warning(person.toString());
personDAO.connectPerson(person);
return "redirect:/registerbook";
}
#RequestMapping(value = "/registerbook", method = RequestMethod.GET)
public ModelAndView registerbook() {
//model.addAttribute("newborrow", new Borrows());
return new ModelAndView("registerbook", "newborrow", new Borrows());
}
#RequestMapping(value = "/registerbook", method = RequestMethod.POST)
public String regbook(#ModelAttribute("newborrow") Borrows borrows, ModelMap model) {
logger.warning(String.valueOf(borrows.getId()));
model.addAttribute("borrowid", borrows.getId());
model.addAttribute("personid", borrows.getStudentid());
model.addAttribute("bookid", borrows.getBookid());
Date today = new Date();
Calendar cal = new GregorianCalendar();
cal.setTime(today);
cal.add(Calendar.DAY_OF_MONTH, -30);
Date today30 = cal.getTime();
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
Timestamp todays30 = Timestamp.valueOf(dateFormat.format(today30));
Timestamp todayy = Timestamp.valueOf(dateFormat.format(today));
borrows.setTakendate(todayy);
borrows.setBroughtdate(todays30);
borrowsDAO.insertBorrow(borrows);
return "hello";
}
#RequestMapping(value = "/addauth", method = RequestMethod.GET)
public ModelAndView addauth() {
return new ModelAndView("addauthbooks", "adding", new Authorz());
}
#RequestMapping(value = "/example", method = RequestMethod.POST)
public String addingauthor(#ModelAttribute Authorz authorz, ModelMap model) {
model.addAttribute("id_author", authorz.getAuthorid());
model.addAttribute("fname_author", authorz.getName());
model.addAttribute("lname_author", authorz.getSurname());
logger.warning(String.valueOf(authorz.getAuthorid()));
logger.warning(authorz.getName());
logger.warning(authorz.getSurname());
authorzDAO.insertAuthorz(authorz);
return "example";
}
#RequestMapping(value = "/addbooks", method = RequestMethod.GET)
public ModelAndView addbook() {
return new ModelAndView("addbook", "addingbook", new Books());
}
#RequestMapping(value = "/admin", method = RequestMethod.POST)
public String addingbook(#ModelAttribute Books books, ModelMap model) {
model.addAttribute("id", books.getId());
model.addAttribute("name", books.getName());
model.addAttribute("pagecount", books.getPagecount());
model.addAttribute("point", books.getPoint());
model.addAttribute("authorid", books.getAuthorid());
model.addAttribute("typeid", books.getTypeid());
model.addAttribute("fragment", books.getFragment());
logger.warning(String.valueOf(books.getId()));
logger.warning(books.getName());
logger.warning(String.valueOf(books.getPagecount()));
booksDAO.insertBook(books);
return "admin";
}
#RequestMapping(value = "/deleteauth", method = RequestMethod.GET)
public ModelAndView deleteauthbooks() {
return new ModelAndView("deleteauthbooks", "deletingauthor", new Authorz());
}
#RequestMapping(value = "/admins", method = RequestMethod.POST)
public String deleteresult(#ModelAttribute Authorz authorz, ModelMap model) {
model.addAttribute("id", authorz.getAuthorid());
model.addAttribute("name", authorz.getName());
model.addAttribute("surname", authorz.getSurname());
authorzDAO.delete_book(authorz.getSurname());
return "admin";
}
#RequestMapping(value = "/deletebooks", method = RequestMethod.GET)
public ModelAndView deletebook() {
return new ModelAndView("deletebooks", "deletingbook", new Books());
}
#RequestMapping(value = "/nadmin", method = RequestMethod.POST)
public String deletebookresult(#ModelAttribute Books books, ModelMap model) {
model.addAttribute("id", books.getId());
model.addAttribute("name", books.getName());
model.addAttribute("pagecount", books.getPagecount());
model.addAttribute("point", books.getPoint());
model.addAttribute("authid", books.getAuthorid());
model.addAttribute("typeid", books.getTypeid());
booksDAO.delete_book(books.getName());
return "admin";
}
#RequestMapping(value = "/borrow", method = RequestMethod.GET)
public ModelAndView borrows() {
return new ModelAndView("borrow", "borrowing", new LoginPerson());
}
#RequestMapping(value = "/res", method = RequestMethod.POST)
public String borrow(#ModelAttribute LoginPerson borrows, ModelMap model) {
logger.warning(borrows.getEmail());
List list_borrows = personDAO.searchStudent(borrows.getEmail());
logger.warning(list_borrows.toString());
model.addAttribute("borrow", list_borrows);
return "result";
}
#RequestMapping(value = "/changebook", method = RequestMethod.GET)
public ModelAndView change() {
return new ModelAndView("changebook", "changing", new Person());
}
#RequestMapping(value = "/changebook", method = RequestMethod.POST)
public String changebook(#ModelAttribute("changebook") Person point, ModelMap model, HttpServletRequest request) {
model.addAttribute("point", point.getPoint());
model.addAttribute("email", point.getEmail());
logger.warning("Upper");
logger.warning(String.valueOf(point.getPoint()));
logger.warning(point.getEmail());
logger.warning(request.getParameter("email"));
if(point.getPoint() != null && request.getParameter("email") != null) {
logger.warning("It works!!!");
personDAO.changeBook(point.getPoint(), request.getParameter("email"));
}
logger.warning("Down");
return "changebook";
}
}
This is my jsp of registration:
<%# taglib prefix="form" uri="http://www.springframework.org/tags/form" %>
<%# taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%--
Created by IntelliJ IDEA.
User: lado
Date: 2019-05-19
Time: 17:48
To change this template use File | Settings | File Templates.
--%>
<%# page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Registration</title>
<link href="//netdna.bootstrapcdn.com/twitter-bootstrap/2.3.2/css/bootstrap-combined.min.css" rel="stylesheet" id="bootstrap-css">
<script src="//netdna.bootstrapcdn.com/twitter-bootstrap/2.3.2/js/bootstrap.min.js"></script>
<script src="//code.jquery.com/jquery-1.11.1.min.js"></script>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
</head>
<body>
<center><h2>Person Information</h2></center>
<%--<form:form method = "post" action = "/springlab_war_exploded/admin" modelAttribute="person">--%>
<form:form method ="post" modelAttribute="person">
<fieldset>
<center>
<div id="legend">
<legend class="">Registration</legend>
</div>
</center>
<center>
<div class="control-group">
<!-- id -->
<label class="control-label" for="id">Id:</label>
<div class="controls">
<input type="number" id="id" name="id" placeholder="" class="input-xlarge">
<p class="help-block">Id can contain only numbers</p>
</div>
</div>
<div class="control-group">
<!-- name -->
<label class="control-label" for="name">First name:</label>
<div class="controls">
<input type="text" id="name" name="name" placeholder="" class="input-xlarge">
<p class="help-block">First name can contain any letters or numbers, without spaces</p>
</div>
</div>
<div class="control-group">
<!-- surname -->
<label class="control-label" for="surname">Last name:</label>
<div class="controls">
<input type="text" id="surname" name="surname" placeholder="" class="input-xlarge">
<p class="help-block">Last name can contain any letters or numbers, without spaces</p>
</div>
</div>
<div class="control-group">
<!-- E-mail -->
<label class="control-label" for="email">Email:</label>
<div class="controls">
<input type="email" id="email" name="email" placeholder="" class="input-xlarge">
<p class="help-block">Please provide your Email</p>
</div>
</div>
<div class="control-group">
<!-- Password-->
<label class="control-label" for="pass">Password:</label>
<div class="controls">
<input type="password" id="pass" name="pass" placeholder="" class="input-xlarge">
<p class="help-block">Password should be at least 4 characters</p>
</div>
</div>
<div class="control-group">
<!-- Date -->
<label class="control-label" for="birthdate">Date:</label>
<div class="controls">
<input type="datetime" id="birthdate" name="birthdate" placeholder="" class="input-xlarge">
<p class="help-block">Please enter your birthdate</p>
</div>
</div>
<div class="control-group">
<!-- Sex -->
<label class="control-label" for="gender">Sex:</label>
<div class="controls">
<input type="text" id="gender" name="gender" placeholder="" class="input-xlarge">
<p class="help-block">Please enter your gender only M or F</p>
</div>
</div>
<div class="control-group">
<!-- Class -->
<label class="control-label" for="job">Job:</label>
<div class="controls">
<input type="text" id="job" name="job" placeholder="" class="input-xlarge">
<p class="help-block">Job can contain any letters or numbers, without spaces</p>
</div>
</div>
<div class="control-group">
<!-- Point -->
<label class="control-label" for="point">Point:</label>
<div class="controls">
<input type="number" id="point" name="point" placeholder="" class="input-xlarge">
<p class="help-block">Point can contain only numbers</p>
</div>
</div>
<div class="control-group">
<!-- Phone number -->
<label class="control-label" for="phonenumber">Phone number:</label>
<div class="controls">
<input type="tel" id="phonenumber" name="phonenumber" placeholder="" class="input-xlarge">
<p class="help-block">Please enter your phone number</p>
</div>
</div>
<div class="control-group">
<!-- Button -->
<div class="controls">
<button class="btn btn-success" name="submit" value="submit">Next</button>
</div>
</div>
</center>
</fieldset>
</form:form>
</body>
</html>
And my jsp register book
<%# taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%# taglib prefix="form" uri="http://www.springframework.org/tags/form" %>
<%--
Created by IntelliJ IDEA.
User: lado
Date: 2019-06-02
Time: 12:51
To change this template use File | Settings | File Templates.
--%>
<%# page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Register Book</title>
<link href="//netdna.bootstrapcdn.com/twitter-bootstrap/2.3.2/css/bootstrap-combined.min.css" rel="stylesheet" id="bootstrap-css">
<script src="//netdna.bootstrapcdn.com/twitter-bootstrap/2.3.2/js/bootstrap.min.js"></script>
<script src="//code.jquery.com/jquery-1.11.1.min.js"></script>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
</head>
<body>
<%--<form:form class="form-horizontal" action='/springlab_war_exploded/login' method="post">--%>
<form:form class="form-horizontal" action="/springlab_war_exploded/login" method="post" modelAttribute="newborrow">
<fieldset>
<div id="legend">
<legend class="">Register Book</legend>
</div>
<div class="control-group">
<!-- id -->
<%--<label class="control-label" for="borrowid">Borrow Id:</label>--%>
<div class="controls">
<form:label path="id">Borrow Id:</form:label>
<form:input path="id"/>
<%--<input type="number" id="borrowid" name="borrowid" placeholder="" class="input-xlarge">--%>
<p class="help-block">Enter borrow id(it is your id)</p>
</div>
</div>
<div class="control-group">
<!-- name -->
<%--<label class="control-label" for="personid">Person Id:</label>--%>
<div class="controls">
<form:label path="studentid">Person Id:</form:label>
<form:input path="studentid"/>
<%--<input type="number" id="personid" name="personid" placeholder="" class="input-xlarge">--%>
<p class="help-block">Eneter person id(it is your id)</p>
</div>
</div>
<div class="control-group">
<!-- surname -->
<%--<label class="control-label" for="bookid">Book Id:</label>--%>
<div class="controls">
<form:label path="bookid">Book Id:</form:label>
<form:input path="bookid"/>
<%--<input type="number" id="bookid" name="bookid" placeholder="" class="input-xlarge">--%>
<p class="help-block">Enter book id</p>
</div>
</div>
<div class="control-group">
<!-- Button -->
<div class="controls">
<button class="btn btn-success" name="submit" value="submit">Submit</button>
</div>
</div>
</fieldset>
</form:form>
</body>
</html>
Don't need "/" while redirecting or forwarding a request.
Can you try "redirect:registerbook";
I am trying to use Spring to read in the statuses that I have found on Twitter & Facebook and post them to a SQLite database.
Whenever I try to run my Spring project, I get the following error:
Neither BindingResult nor plain target object for bean name 'facebookModel' available as request attribute
I have looked at other pages on Stack Overflow and I have seen the following:
model.addAttribute("facebookModel", new FacebookModel());
but it hasn't been working for me. I was wondering could anyone explain to me how I would go about fixing the problem.
Here is my controller:
package adam.social.media.controller;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.social.facebook.api.Facebook;
import org.springframework.social.facebook.api.Post;
import org.springframework.social.facebook.api.impl.FacebookTemplate;
import org.springframework.social.twitter.api.Tweet;
import org.springframework.social.twitter.api.Twitter;
import org.springframework.social.twitter.api.impl.TwitterTemplate;
import org.springframework.stereotype.Controller;
import org.springframework.validation.BindingResult;
import org.springframework.validation.ObjectError;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.servlet.ModelAndView;
import adam.social.media.model.FacebookModel;
import adam.social.media.model.TwitterModel;
import adam.social.media.repository.FacebookRepository;
import adam.social.media.repository.TwitterRepository;
#Controller(value = "/socialmedia")
public class SocialMediaController {
private Facebook facebook;
private Twitter twitter;
private FacebookRepository facebookRepository;
private TwitterRepository twitterRepository;
private static Logger logger = Logger.getLogger(SocialMediaController.class
.getName());
#Autowired
public SocialMediaController(FacebookRepository facebookRepository, TwitterRepository twitterRepository) {
logger.debug("ENTERING SocialMediaController");
this.facebookRepository = facebookRepository;
this.twitterRepository = twitterRepository;
logger.debug("EXITING SocialMediaController");
}
#RequestMapping(value = "/facebook/get", method = RequestMethod.GET)
public ModelAndView getFacebookStatus(FacebookModel facebookModel) {
logger.debug("ENTERING getFacebookStatus");
facebook = new FacebookTemplate("CAACEdEose0cBAJxfcf9xRQsL5un1WeEyIe2dy2xjI0EmuwzNbCWCPrTGwbsukRfQNb5ojQepPsMEjZAEXVwWfbYNA2fQO72kS3SPimt3ZCud4ykUZCoFkxZC6ks64dneZCNXLLJGRcqLeQ6DBPGwMrWtaSfi3W0zJLwDG1eu5FUsWJzgVZBwV4RmQvhhR4Yh0JfmyJSEU5am4L7rYJTUK0GtcYflhYlDMZD");
ModelAndView modelAndView = new ModelAndView("index");
// PagedList<Post> posts = facebook.feedOperations().getFeed();
// for(Post post : posts) { System.out.println(post.getMessage()); }
Post post = facebook.feedOperations().getFeed().get(0);
facebookModel.setPostId(post.getId());
// facebookModel.setToProfile(post.getTo().get(0).getName());
facebookModel.setToProfile("Hi");
facebookModel.setFromProfile(post.getFrom().getName());
facebookModel.setCreatedTime(post.getCreatedTime());
facebookModel.setUpdatedTime(post.getUpdatedTime());
facebookModel.setMessage(post.getMessage());
facebookModel.setPictureUrl(post.getPicture());
modelAndView.addObject("facebookModel", facebookModel);
logger.debug("EXITING getFacebookStatus");
return modelAndView;
}
#RequestMapping(value = "/twitter/get", method = RequestMethod.GET)
public ModelAndView getTwitterStatus(TwitterModel twitterModel) {
logger.debug("ENTERING getTwitterStatus");
twitter = new TwitterTemplate("");
ModelAndView modelAndView = new ModelAndView("index");
// PagedList<Post> posts = twitter.feedOperations().getFeed();
// for(Post post : posts) { System.out.println(post.getMessage()); }
Tweet tweet = twitter.timelineOperations().getHomeTimeline().get(0);
twitterModel.setPostId(2);
twitterModel.setFromProfile("3");
twitterModel.setMessage("1");
modelAndView.addObject("twitterModel", twitterModel);
logger.debug("EXITING getTwitterStatus");
return modelAndView;
}
#RequestMapping(value = "/facebook/post", method = RequestMethod.POST)
public ModelAndView postFacebookStatus(FacebookModel facebookModel, BindingResult result) {
logger.debug("ENTERING postFacebookStatus");
if (result.hasErrors()) {
Map<String, Object> params = new HashMap<String, Object>();
List<ObjectError> errors = result.getAllErrors();
params.put("facebookModel", facebookModel);
params.put("errors", errors);
return new ModelAndView("inddex", params);
}
facebookRepository.saveAndFlush(facebookModel);
logger.debug("EXITING postFacebookStatus");
return new ModelAndView("redirect:/index.html");
}
#RequestMapping(value = "/twitter/post", method = RequestMethod.POST)
public ModelAndView postTwitterStatus(TwitterModel twitterModel, BindingResult result) {
logger.debug("ENTERING postTwitterStatus");
if (result.hasErrors()) {
Map<String, Object> params = new HashMap<String, Object>();
List<ObjectError> errors = result.getAllErrors();
params.put("twitterModel", twitterModel);
params.put("errors", errors);
return new ModelAndView("inddex", params);
}
twitterRepository.saveAndFlush(twitterModel);
logger.debug("EXITING postTwitterStatus");
return new ModelAndView("redirect:/index.html");
}
}
Here is my JSP:
<%# taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
<%# taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<%# taglib prefix="form" uri="http://www.springframework.org/tags/form"%>
<head>
<title>Social Media</title>
</head>
<body>
<form:form modelAttribute="facebookModel" method="POST" commandName="facebookModel">
<form:hidden path="id" />
<form:hidden path="postId" />
<form:hidden path="toProfile" />
<form:hidden path="fromProfile" />
<form:hidden path="createdTime" />
<form:hidden path="updatedTime" />
<form:hidden path="message" />
<form:hidden path="pictureUrl" />
<button name="submit" type="submit" value="Save" style="background-color: rgba(255, 255, 255, 1); border: none; outline: none; cursor: pointer">
<img src="<c:url value="images/facebook.png"/>" />
</button>
</form:form>
<form:form modelAttribute="twitterModel" method="POST" commandName="twitterModel">
<form:hidden path="id" />
<form:hidden path="postId" />
<form:hidden path="toProfile" />
<form:hidden path="fromProfile" />
<form:hidden path="createdTime" />
<form:hidden path="updatedTime" />
<form:hidden path="message" />
<form:hidden path="pictureUrl" />
<button name="submit" type="submit" value="Save" style="background-color: rgba(255, 255, 255, 1); border: none; outline: none; cursor: pointer">
<img src="<c:url value="images/twitter.png"/>" />
</button>
</form:form>
</body>
</body>
Thanks in advance,
Adam Barry
It's because you are trying to obtain model attribute before setting it in.
I.e. in getFacebookStatus method, you are obtaining FacebookModel and I don't see that you set it anywhere before of that. Solution would be just to create new instance of FacebookModel and to set it as a model attribute.
Basically, something like this:
#RequestMapping(value = "/facebook/get", method = RequestMethod.GET)
public ModelAndView getFacebookStatus() {
logger.debug("ENTERING getFacebookStatus");
facebook = new FacebookTemplate("CAACEdEose0cBAJxfcf9xRQsL5un1WeEyIe2dy2xjI0EmuwzNbCWCPrTGwbsukRfQNb5ojQepPsMEjZAEXVwWfbYNA2fQO72kS3SPimt3ZCud4ykUZCoFkxZC6ks64dneZCNXLLJGRcqLeQ6DBPGwMrWtaSfi3W0zJLwDG1eu5FUsWJzgVZBwV4RmQvhhR4Yh0JfmyJSEU5am4L7rYJTUK0GtcYflhYlDMZD");
ModelAndView modelAndView = new ModelAndView("index");
// PagedList<Post> posts = facebook.feedOperations().getFeed();
// for(Post post : posts) { System.out.println(post.getMessage()); }
Post post = facebook.feedOperations().getFeed().get(0);
FacebookModel facebookModel = new FacebookModel();
facebookModel.setPostId(post.getId());
// facebookModel.setToProfile(post.getTo().get(0).getName());
facebookModel.setToProfile("Hi");
facebookModel.setFromProfile(post.getFrom().getName());
facebookModel.setCreatedTime(post.getCreatedTime());
facebookModel.setUpdatedTime(post.getUpdatedTime());
facebookModel.setMessage(post.getMessage());
facebookModel.setPictureUrl(post.getPicture());
modelAndView.addObject("facebookModel", facebookModel);
logger.debug("EXITING getFacebookStatus");
return modelAndView;
}
To obtain model attribute:
#RequestMapping(value = "/facebook/post", method = RequestMethod.POST)
public ModelAndView postFacebookStatus(#ModelAttribute("facebookModel") FacebookModel facebookModel, BindingResult result) {
....
}
I'm newer to Spring and Java and working on getting a form to work in Spring MVC, using JSP, JSTL, Hibernate/JPA and a model class. I can get the page to display fine, but the post that is supposed to create the user is giving me an error.
Failed to convert property value of type java.lang.String to required type com.everesttech.recruiting.searchtool.entity.Role for property user.role; nested exception is java.lang.IllegalStateException: Cannot convert value of type [java.lang.String] to required type [com.everesttech.recruiting.searchtool.entity.Role] for property role: no matching editors or conversion strategy found
This error makes sense because the form is passing back an ID for the Role while the User object expects a Role object to be passed. However I'm not sure how to work around this, while still allowing my JSP to be backed by my actual Entity objects as I want to use Spring/Hibernate validations. Is there just a way to declare that form:select as a Role object? Any advice or solutions are much appreciated. Thanks in advanced.
I have provided the relevant sections of code from my project. I did not include code from my service layer and entity layer since I know they are working. However I can include those as well if needed. User has a many to one relationship with Role.
UserController
/**
* display the user add page
*
* #return returns the view name
*/
#RequestMapping(value="/user/add", method=RequestMethod.GET)
public ModelAndView showUserAdd(ServletRequest request, #ModelAttribute("userModel") UserModel userModel, ModelMap modelmap) {
ModelMap modelMap = new ModelMap();
userModel.setUser(new User());
userModel.setRoles(userService.getRoles());
modelMap.addAttribute("userModel", userModel);
return new ModelAndView("user/add", modelMap);
}
/**
* handle post request to handle user creation, if successful displays user list page
*
* #param user User object from JSP
* #param result BindingResult from JSP
* #return returns view name
*/
#RequestMapping(value="/user/add", method=RequestMethod.POST)
public String userAdd(UserModel userModel, BindingResult result) {
if (result.hasErrors()) {
logger.warn("Error binding UserModel for /user/add, returning to previous page");
List<ObjectError> errors = result.getAllErrors();
for (ObjectError error : errors) {
logger.warn(error.getCode() + " - " + error.getDefaultMessage());
}
return "user/add";
}
try {
User user = userModel.getUser();
userService.addUser(user);
}
catch (DuplicateKeyException e) {
logger.warn("Duplicate record found in User table", e);
}
catch (Exception e) {
logger.error("Error occurred while trying to create a new user", e);
}
return "/user";
}
This is the model I am passing to the JSP witch contains a User object, which is the Hibernate Entity, and a list of Roles, another hibernate Entity.
import java.util.List;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
import com.everesttech.recruiting.searchtool.entity.Role;
import com.everesttech.recruiting.searchtool.entity.User;
#Scope(value="request")
#Component("userModel")
public class UserModel {
public User user;
public List<Role> roles;
public UserModel() {
}
public UserModel(User user, List<Role> roles) {
this.user = user;
this.roles = roles;
}
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
public List<Role> getRoles() {
return roles;
}
public void setRoles(List<Role> roles) {
this.roles = roles;
}
#Override
public String toString() {
return "UserModel [user=" + user + ", roles=" + roles + "]";
}
}
Here is my JSP.
<%# taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%# taglib prefix="sf" uri="http://www.springframework.org/tags/form" %>
<%# taglib prefix="spring" uri="http://www.springframework.org/tags" %>
<div class="container">
<div class="row">
<div class="col-xs-12 col-sm-8 col-md-6">
<h3>User - Add</h3>
<br>
<spring:hasBindErrors name="userModel">
<div class="alert alert-danger">
<sf:errors path="userModel.user.firstName"></sf:errors>
<sf:errors path="userModel.user.lastName"></sf:errors>
<sf:errors path="userModel.user.email"></sf:errors>
<sf:errors path="userModel.user.userName"></sf:errors>
<sf:errors path="userModel.user.password"></sf:errors>
<sf:errors path="userModel.user.role"></sf:errors>
</div>
</spring:hasBindErrors>
<c:url var="formAction" value="/user/add" />
<sf:form commandName="userModel" modelAttribute="userModel" method="post" action="${formAction}">
<div class="form-group">
<label for="first-name">First Name</label>
<sf:input path="user.firstName" id="first-name" class="form-control" placeholder="First Name" />
</div>
<div class="form-group">
<label for="last-name">Last Name</label>
<sf:input path="user.lastName" id="last-name" class="form-control" placeholder="Last Name" />
</div>
<div class="form-group">
<label for="email">Email</label>
<sf:input path="user.email" id="email" class="form-control" placeholder="Email" />
</div>
<div class="form-group">
<label for="user-name">Username</label>
<sf:input path="user.userName" id="user-name" class="form-control" placeholder="Username" />
</div>
<div class="form-group">
<label for="password">Password</label>
<sf:password path="user.password" id="password" class="form-control" placeholder="" />
</div>
<div class="form-group">
<label for="confirm-password">Confirm Password</label>
<input type="password" id="confirm-password" class="form-control" placeholder="" />
</div>
<div class="form-group">
<label for="role">Role</label>
<sf:select path="user.role" id="role" class="form-control" >
<c:forEach var="r" items="${userModel.roles}">
<sf:option value="${r.getId()}">${r.getFriendlyName()}</sf:option>
</c:forEach>
</sf:select>
</div>
<button type="submit" class="btn btn-default">Save</button>
<button type="button" class="btn btn-default">Cancel</button>
</sf:form>
</div>
</div>
</div>
For anyone interested I found a solution in the Spring documentation. I had to create a class which would handle the conversion from String to Role and register it. This has to make a trip to the database to create the Role object but I don't see another way of handling it.
Here is my class.
import javax.inject.Inject;
import org.springframework.core.convert.converter.Converter;
import com.everesttech.recruiting.searchtool.dao.RoleDao;
import com.everesttech.recruiting.searchtool.entity.Role;
final class StringToRole implements Converter<String, Role> {
#Inject
RoleDao roleDao;
#Override
public Role convert(String source) {
return roleDao.find(Long.parseLong(source));
}
}
I added/edited the following in my mvc-context.xml file.
<!-- Enables the Spring MVC #Controller programming model -->
<mvc:annotation-driven conversion-service="conversionService"></mvc:annotation-driven>
<bean id="conversionService"
class="org.springframework.context.support.ConversionServiceFactoryBean">
<property name="converters">
<list>
<bean class="com.examplecompany.exampleapp.example.converter.StringToRole"/>
</list>
</property>
</bean>
This works and I'm now able to submit the form with no issues. However now my hibernate validations are not appearing on the JSP when the User object does not meet the validation requirements. As an example First Name has a #NotBlank annotation. I can see that is being detected and I'm logging it. However they are not appearing on the jsp in the form:error tags. If anyone knows how to solve that issue please let me know.
Ok I'm stumped. I am writing a Spring based app that queries a web service for information to load a SELECT object based on the user's id. I've set up the web.xml and servlet xml files, design the initial page and have a redirect from an index.jsp file (the final system will reside under a Tomcat / IIS config) with a hard coded value for the username for the time being.
Every time I try to run it I get a 404 error and nothing in the Tomcat logs. I am relatively new to JSP / Spring so this is driving me nuts as I can't seem to find the problem.
I have tried removing the reference to the web service calls and still the pages to not load.
What am I missing?
Below is the code minus stylesheets and images:
UserDatabaseProject.java
/**
*
*/
package enterprisesearch.domain;
/**
* #author bob
*
*/
public class UserDatabaseProject
{
private String _msUserName = "";
private String _msDatabaseName = "";
private String _msDatabaseDescription = "";
private String _msProjectName = "";
private String _msProjectDescription = "";
public UserDatabaseProject()
{
}
public UserDatabaseProject(String psUserName, String psDatabaseName, String psDatabaseDescription, String psProjectName, String psProjectDescription)
{
this._msUserName = psUserName;
this._msDatabaseName = psDatabaseName;
this._msDatabaseDescription = psDatabaseDescription;
this.setProjectName(psProjectName);
this.setProjectDescription(psProjectDescription);
}
/**
* #return the _msProjectName
*/
public final String getProjectName()
{
return this._msProjectName;
}
/**
* #param _msProjectName the _msProjectName to set
*/
public final void setProjectName(String psProjectName)
{
this._msProjectName = psProjectName;
}
/**
* #return the _msProjectDescription
*/
public final String getProjectDescription()
{
return this._msProjectDescription;
}
/**
* #param _msProjectDescription the _msProjectDescription to set
*/
public final void setProjectDescription(String psProjectDescription)
{
this._msProjectDescription = psProjectDescription;
}
/**
* #return the _msUserName
*/
public final String getUserName()
{
return this._msUserName;
}
/**
* #param _msUserName the _msUserName to set
*/
public final void setUserName(String psUserName)
{
this._msUserName = psUserName;
}
/**
* #return the _msDatabaseName
*/
public final String getDatabaseName()
{
return this._msDatabaseName;
}
/**
* #param _msDatabaseName the _msDatabaseName to set
*/
public final void setDatabaseName(String psDatabaseName)
{
this._msDatabaseName = psDatabaseName;
}
/**
* #return the _msDatabaseDescription
*/
public final String getDatabaseDescription()
{
return this._msDatabaseDescription;
}
/**
* #param _msDatabaseDescription the _msDatabaseDescription to set
*/
public final void setDatabaseDescription(String psDatabaseDescription)
{
this._msDatabaseDescription = psDatabaseDescription;
}
}
DouglasService.java
/**
*
*/
package enterprisesearch.domain.service;
import java.io.StringReader;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathExpressionException;
import javax.xml.xpath.XPathFactory;
import org.apache.cxf.jaxws.JaxWsProxyFactoryBean;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;
import gov.sec.com.IDouglas;
import enterprisesearch.domain.UserDatabaseProject;
/**
* #author bob
*
*/
public class DouglasService
{
private IDouglas _mtDouglas;
private static Map<Integer, UserDatabaseProject> _muspUserDatabaseProjects = new HashMap<Integer, UserDatabaseProject>();
public DouglasService(String psDouglasUrl)
{
//String endPointAddress = "http://localhost:8080/Douglas/services/Douglas?wsdl";
//ApplicationContext acContext = new ClassPathXmlApplicationContext("context.xml");
JaxWsProxyFactoryBean factory = new JaxWsProxyFactoryBean();
factory.setServiceClass(IDouglas.class);
factory.setAddress(psDouglasUrl);
this._mtDouglas = (IDouglas) factory.create();
}
public String getSecurityToken(String psUserId)
{
String sReturn = "";
this._mtDouglas.getSecurityToken(psUserId);
return sReturn;
}
public String getProjectOptions(String psProjectName)
{
String sReturn = "";
this._mtDouglas.getProjectOptions(psProjectName);
return sReturn;
}
public String getDatabaseFilters(String psDatabaseName)
{
String sReturn = "";
this._mtDouglas.getDatabaseFilters(psDatabaseName);
return sReturn;
}
public Collection<UserDatabaseProject> getUserDatabaseProjects(String psUserName)
{
String sReturn = "";
String sResult = this._mtDouglas.getUserDatabaseProjects(psUserName);
XPathFactory xfactory = XPathFactory.newInstance();
XPath xPath = xfactory.newXPath();
StringReader sr = new StringReader(sResult);
NodeList databases = null;
try
{
databases = (NodeList) xPath.evaluate("/douglasresponse/responsedata/databases", new InputSource(new StringReader(sResult)), XPathConstants.NODESET);
for (int i = 0; i < databases.getLength(); i++)
{
Element elDatabase = (Element) databases.item(i);
String sUserName = xPath.evaluate("database/username", elDatabase);
String sDatabaseName = xPath.evaluate("database/databasename", elDatabase);
String sDatabaseDescription = xPath.evaluate("database/databasedescription", elDatabase);
String sProjectName = xPath.evaluate("database/projectname", elDatabase);
String sProjectDescription = xPath.evaluate("database/projectdescription", elDatabase);
this._muspUserDatabaseProjects.put(new Integer(i), new UserDatabaseProject(sUserName, sDatabaseName, sDatabaseDescription, sProjectName, sProjectDescription));
}
}
catch(XPathExpressionException ex)
{
System.out.print(ex.getMessage());
}
return _muspUserDatabaseProjects.values();
}
public String executeTextQuery(String psSecurityToken, String psProjectName, String psDatabase, String psQueryText, String psOptions, String psFilters)
{
String sReturn = "";
this._mtDouglas.executeTextQuery(psSecurityToken, psProjectName, psDatabase, psQueryText, psOptions, psFilters);
return sReturn;
}
public String executeGetContent(String psSecurityToken, String psProjects, String psDatabases, String psOptions)
{
String sReturn = "";
this._mtDouglas.executeGetContent(psSecurityToken, psProjects, psDatabases, psOptions);
return sReturn;
}
public String executeGetSimilar(String psSecurityToken, String psProjects, String psDatabases, String psOptions)
{
String sReturn = "";
this._mtDouglas.executeGetSimilar(psSecurityToken, psProjects, psDatabases, psOptions);
return sReturn;
}
}
SearchController.java
package enterprisesearch.web;
import enterprisesearch.domain.UserDatabaseProject;
import enterprisesearch.domain.service.DouglasService;
import java.util.Collection;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
#Controller
public class SearchController
{
//protected final Log logger = LogFactory.getLog(getClass());
private DouglasService dgWebService = new DouglasService("http://localhost:8080/Douglas/services/Douglas");
#RequestMapping("/search.html")
#ModelAttribute("userprojects")
public Collection<UserDatabaseProject> getUserProjects(#RequestParam(value="username", required=true) String psUsername)
{
return this.dgWebService.getUserDatabaseProjects(psUsername);
}
//#RequestMapping("/search.html")
//#ModelAttribute("testmessage")
//public String setMessage()
//{
// return "This is a test!";
//}
}
/WEB-INF/jsp/index.jsp
<jsp:forward page="search.html">
<jsp:param value="lymana" name="username"/>
</jsp:forward>
/WEB-INF/jsp/search.jsp
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<%# taglib uri="http://www.springframework.org/tags/form" prefix="form"%>
<%# taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%# taglib prefix="x" uri="http://java.sun.com/jsp/jstl/xml" %>
<%# taglib prefix="spring" uri="http://www.springframework.org/tags" %>
<html xmlns="http://www.w3.org/1999/xhtml" >
<head>
<title>Enterprise Search</title>
<link href="assets/style_sheets/main.css" rel="stylesheet" type="text/css" />
<script type="text/javascript" language="javascript" src="assets/scripts/controls.js"></script>
</head>
<body>
<form:form method="post" action="" modelAttribute="search">
<table width="100%" border="0" style="border-collapse:collapse; border-spacing: 0px;" cellspacing="0">
<tr id="pageHeader">
<td id="pageHeaderLeft"><img src="assets/images/OCIE_left-1.jpg" style="float:left;" /></td>
<td id="pageHeaderRight"><img src="assets/images/OCIE_right.jpg" /></td>
</tr>
<tr>
<td valign="top" width="50%">
<div id="leftContainer">
<div class="blockHeader">
Text Search
</div>
<div id="TextBlock" class="blockControl">
<label for="taSearchText">Search Text:</label><br />
<textarea id="taSearchText" cols="60" rows="7" style="margin-bottom: .5em;"></textarea>
<br />
<table border="0" style="border-collapse:collapse; border-spacing: 0px;" cellspacing="0">
<tr>
<td width="30%" style="padding: 0em 0em .5em .5em; text-align:right; vertical-align:middle;">
<label for="sltResultsPerPage">Results per page:</label>
</td>
<td width="30%" style="padding: 0em .5em .5em 0em; text-align:left; vertical-align:middle;">
<select id="sltResultsPerPage">
<option value="10">10 per page</option>
<option value="20">20 per page</option>
<option value="50">50 per page</option>
<option value="100">100 per page</option>
</select>
</td>
<td width="40%" rowspan="3" valign="middle" align="center">
<input id="btnSearch" type="button" value="Search" />
</td>
</tr>
<tr>
<td style="padding: 0em 0em .5em .5em; text-align:right; vertical-align:middle;">
<label for="sltSort">Sort results by:</label>
</td>
<td style="padding: 0em .5em .5em 0em; text-align:left; vertical-align:middle;">
<select id="sltSort">
<option value="relevance">Relevance</option>
<option value="dateAsc">Date (Ascending)</option>
<option value="dateDesc">Date (Descending)</option>
</select>
</td>
</tr>
<tr>
<td style="padding: 0em 0em .5em .5em; text-align:right; vertical-align:middle;">
<label for="sltRelevance">Relevance:</label>
</td>
<td style="padding: 0em .5em .5em 0em; text-align:left; vertical-align:middle;">
<select id="sltRelevance">
<option value="90">90% relevant</option>
<option value="80">80% relevant</option>
<option value="70">70% relevant</option>
<option value="60">60% relevant</option>
<option value="50">50% relevant</option>
</select>
</td>
</tr>
</table>
</div><!-- end of textblock -->
<div class="blockHeader"><img src="assets/images/RightArrowClosed16x16.jpg" onclick="setAdvancedVisible('BooleanBlock');" />
Boolean
</div>
<div id="BooleanBlock" class="blockControl" style="visibility:hidden; display:none;">Boolean Search controls here<br /><br /><br /><br />
</div>
<div class="blockHeader">
<img src="assets/images/RightArrowClosed16x16.jpg" onclick="setAdvancedVisible('ParametricBlock');" />
Parametric
</div>
<div id="ParametricBlock" class="blockControl" style="visibility:hidden; display:none;">Parametric Search controls here<br /><br /><br /><br />
</div>
<div class="blockHeader"><img src="assets/images/RightArrowClosed16x16.jpg" onclick="setAdvancedVisible('ClusterBlock');" />
Cluster
</div>
<div id="ClusterBlock" class="blockControl" style="visibility:hidden; display:none;">Cluster results here<br /><br /><br /><br />
</div>
</div>
</td>
<td valign="top" width="50%">
<div id="rightContainer">
<div class="blockHeader"><img src="assets/images/RightArrowClosed16x16.jpg" onclick="setAdvancedVisible('ProjectsBlock');"/>
Projects
</div>
<div id="ProjectsBlock" class="blockControl">
<label for="sltProjects">Projects:</label><br />
<select id="sltProjects" size="10" onclick="">
<option value="all">All available projects</option>
<c:forEach items="${userprojects}" var="UserDatabaseProject">
<form:option value="${UserDatabaseProject._msProjectName}">${UserDatabaseProject._msProjectDescription}</form:option>
</c:forEach>
</select>
</div>
<div class="blockHeader"><img src="assets/images/RightArrowClosed16x16.jpg" onclick="setAdvancedVisible('DatabasesBlock');"/>
Databases
</div>
<div id="DatabasesBlock" class="blockControl">
<label for="sltDatabases">Databases:</label><br />
<select id="sltDatabases" size="10" onclick="">
<option value="all">All available databases</option>
<option value="dbTCR20">TCR20 Database Primary</option>
<option value="dbTCR20-1">TCR20 Database Secondary</option>
<option value="dbECC">ECC Emails</option>
</select>
</div>
<div class="blockHeader"><img src="assets/images/RightArrowClosed16x16.jpg" onclick="setAdvancedVisible('FiltersBlock');"/>
Filters
</div>
<div id="FiltersBlock" class="blockControl">
<label for="sltFilters">Filters:</label><br />
<select id="sltFilters" size="10" onclick="createInput();" multiple="multiple" >
<option value="Comment">TCR20 - Comment</option>
<option value="TCR Subject">TCR20 - Subject</option>
<option value="From Address">ECC - From Address</option>
<option value="ECC Subject">ECC - Subject</option>
<option value="Message Text">ECC - Message Text</option>
</select>
</div>
<div class="blockHeader"><img src="assets/images/RightArrowClosed16x16.jpg" onclick="setAdvancedVisible('SelectedBlock');"/>
<span>Selected Filters</span>
</div>
<div id="SelectedBlock" class="blockControl">
</div>
</div>
</td>
</tr>
<tr>
<td colspan="2">
<hr />
<div>
<div class="resultsHeader">
Search Results
</div>
<div class="resultsControl" style="margin-bottom: 15px;">
</div>
</div>
</td>
</tr>
<tr>
<td id="footer" colspan="2"><hr />Some footer stuff goes here!</td>
</tr>
</table>
</form:form>
</body>
</html>
web.xml
<?xml version="1.0" encoding="ISO-8859-1"?>
<web-app version="2.4"
xmlns="http://java.sun.com/xml/ns/j2ee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
<!-- Register a servlet that despatches requests to registered controllers -->
<servlet>
<servlet-name>es</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<!-- Send all .html files to the Spring dispatcher servlet -->
<servlet-mapping>
<servlet-name>es</servlet-name>
<url-pattern>*.html</url-pattern>
</servlet-mapping>
<!-- Define the web application entry point -->
<welcome-file-list>
<welcome-file>index.html</welcome-file>
</welcome-file-list>
</web-app>
es.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-2.5.xsd">
<!-- Auto-detect controllers in this package -->
<context:component-scan base-package="enterprisesearch.web"/>
<!-- Prepend /WEB-INF/jsp/ and append .jsp to the view name -->
<bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/jsp/"/>
<property name="suffix" value=".jsp"/>
</bean>
</beans>
Your controller is bound to <contextname>/search.html, not index.html - <contextname> referring to the context that Tomcat maps your application to, which usually is the name of the WAR file but can be anything if you have configured Tomcat specially.
Turn up Spring's logging and you will see it logging warnings when you request a URL that it has no mapping for.
your controller was worng, you must return a ModalAndView or NameOfView not Collection<UserDatabaseProject>
please try this :
#RequestMapping("/search.html")
#ModelAttribute("userprojects")
public ModelAndMap getUserProjects(#RequestParam(value="username", required=true) String psUsername){
ModelMap modelMap = new ModelMap();
modelMap.put("userprojects", this.dgWebService.getUserDatabaseProjects(psUsername));
return new ModelAndView("index", modelMap);
}
Follow any good tutorial on spring mvc.
your return type should be either ModelAndView or its related type (since you are using InternalResourceViewResolved) or the String name of view.
In case of Rest Based approach or ajax you can return the data as collection (which get converted into json). For this approach you need to mark your controller as #RestController on class level or #ResponseBody on method level. This approach is mostly used in Ajax calls in which you need to iterate through the json response received and set the data on that page.
In Spring mvc based approach you need to add all the objects in the ModelAndView and set the view name as below. Then you can access the objects on that view using el.
#RequestMapping("/search.html")
#ModelAttribute("userprojects")
public ModelAndView getUserProjects(#RequestParam(value="username", required=true) String psUsername){
ModelAndView modelAndView = new ModelAndView();
// add all the required data which you need on next view page
modelAndView.addObject("userprojects", this.dgWebService.getUserDatabaseProjects(psUsername));
// set the view name which needs to be displayed
modelAndView.setViewName("search");
return modelAndView
}
In Jsp access the userprojects as:
${userprojects._msProjectName}