I am stuck with a problem at a Spring Boot project. To take it short: I'm creating a photo archive and want to save multiple photos to each event. I created Photo and Event objects with annotations to use jpa/Hibernate. Also structured the project using repositories, services and controllers. Built a form to create the events. Index page shows all events plus button to upload a photo to the specific event.
And that's where the problem starts. I can create exactly one photo for each event despite I am creating a new Photo object at the controller and pass it to the Thymeleaf template for photo creation form. When filling the form again I am overwriting the data of the single existing photo and I have no clue why.
Photo Class:
#Entity
#Table(name = "photographies")
public class Photo {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private long id;
#Column(unique = true, nullable = false)
private String label;
private String photographer;
#ManyToOne(fetch = FetchType.LAZY)
#JsonIgnore
private Event event;
//#Column(nullable = false)
private Blob image;
private Date date;
public Photo(){};
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getLabel() {
return label;
}
public void setLabel(String label) {
this.label = label;
}
public String getPhotographer() {
return photographer;
}
public void setPhotographer(String photographer) {
this.photographer = photographer;
}
public Event getEvent() {
return event;
}
public void setEvent(Event event) {
this.event = event;
}
public Blob getImage() {
return image;
}
public void setImage(Blob image) {
this.image = image;
}
public Date getDate() {
return date;
}
public void setDate(Date date) {
this.date = date;
}
public void assignEvent(Event event){
this.event = event;
event.getPhotos().add(this);
}
#Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Photo photo = (Photo) o;
return id == photo.id && Objects.equals(label, photo.label) && Objects.equals(photographer, photo.photographer) && Objects.equals(event, photo.event) && Objects.equals(image, photo.image) && Objects.equals(date, photo.date);
}
#Override
public int hashCode() {
return Objects.hash(id, label, photographer, event, image, date);
}
}
Event Class:
#Entity
#Table(name = "event")
public class Event {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private long id;
private String label;
#OneToMany(mappedBy = "event", fetch = FetchType.LAZY)
private List<Photo> photos = new LinkedList<>();
public Event(String label) {
this.label = label;
}
public Event(){};
}
#OneToMany(mappedBy = "event", fetch = FetchType.LAZY, cascade = CascadeType.ALL)
private List<Photo> photos = new LinkedList<>();
public Event(String label) {
this.label = label;
}
public Event(){};
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getLabel() {
return label;
}
public void setLabel(String label) {
this.label = label;
}
public List<Photo> getPhotos() {
return photos;
}
public void setPhotos(List<Photo> photos) {
this.photos = photos;
}
public void addPhoto(Photo photo){
photos.add(photo);
}
#Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Event event = (Event) o;
return id == event.id && Objects.equals(label, event.label) && Objects.equals(photos, event.photos);
}
#Override
public int hashCode() {
return Objects.hash(id, label, photos);
}
}
Photo Service:
#Service
public class PhotoService {
#Autowired
private PhotoRepository photoRepository;
public List<Photo> findAllPhotosOrderedByDate() {
return photoRepository.findAllByOrderByDateAsc();
}
public void deletePhoto(long id) {
Photo photo = photoRepository.findById(id).get();
photoRepository.delete(photo);
}
public void savePhoto(Photo photo){
photoRepository.save(photo);
}
public Photo getPhotoById(long id){
return photoRepository.findPhotoById(id);
}
#Transactional
public void assignEvent(Photo photo, long id){
photo.assignEvent(eventRepository.findById(id).get());
photoRepository.save(photo);
}
Event Service:
#Service
public class EventService {
#Autowired
private EventRepository eventrepository;
#Autowired
private PhotoRepository photoRepository;
public List<Event> showEvents() {
return eventrepository.findAll();
}
public void saveEvent(Event event) {
eventrepository.save(event);
}
public void deleteEvent(long id) {
Event deletedEvent = eventrepository.findById(id).get();
for (Photo photo : deletedEvent.getPhotos()){
photo.assignEvent(null);
photoRepository.save(photo);
}
eventrepository.delete(deletedEvent);
}
public Event getEventById(long id){
return eventrepository.findById(id).get();
}
}
Photo Controller:
#Controller
public class PhotoController {
#Autowired
private PhotoService photoService;
#Autowired
private EventService eventService;
#GetMapping("/photo/upload/{id}")
public String uploadPhoto(Model model, #PathVariable long id){
Photo photo = new Photo();
model.addAttribute("photo", photo);
model.addAttribute("id", id);
return "uploadPhoto";
}
#PostMapping("/photo/upload/{id}")
public String uploadPhoto(#ModelAttribute ("photo") Photo photo, #PathVariable long id){
photoService.assignEvent(photo, id);
return "redirect:/";
}
Index html for getting the specific Event-ID when clicking upload button:
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Photo Upload</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap#5.2.1/dist/css/bootstrap.min.css" rel="stylesheet">
</head>
<body>
<nav class="navbar navbar-expand-lg navbar-dark bg-dark">
<a class="navbar-brand"> <img src="/images/sticker.webp" width="50" height="50" alt="An image of Bloome">
<span class="navbar-brand mb-0 h1 fs-3 align-middle">Bloome Fursuit Photographies</span>
</a>
<div class="collapse navbar-collapse" id="navbarSupportedContent">
<ul class="navbar-nav me-auto">
<li class="nav-item">
<a class="nav-link" href="/event/add"><p class="text-light bg-primary m-2 p-2">Create new event</p></a>
</li>
</ul>
</div>
</nav>
<br/>
<div class="container">
<div class="row">
<h1>List of events</h1>
</div>
<br/>
<table class="table table-striped">
<thead class="table-dark">
<tr>
<th scope="col">Label</th>
<th scope="col">Number of photos</th>
<th scope="col">Actions</th>
</tr>
</thead>
<tbody>
<tr th:each = "event : ${events}">
<th scope="row" th:text = "${event.label}"></th>
<td th:text = "${event.photos.size}"></td>
<td>
<a th:href="#{/photo/upload/{id} (id=${event.id})}" class="btn btn-primary">Upload photo</a>
<a th:href="#{/event/delete/{id} (id=${event.id})}" class="btn btn-danger">Delete event</a>
</td>
</tr>
</tbody>
</table>
</div>
</body>
</html>
Photo html form:
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Upload photo</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap#5.2.1/dist/css/bootstrap.min.css" rel="stylesheet">
</head>
<body>
<br/>
<div class="container">
<form th:action = "#{/photo/upload/{id} (id=${id})}" th:object="${photo}" method = "POST">
<div class="form-group row">
<div class="col">
<label for="labelPhoto" class="col-sm-2 col-form-label col-form-label-lg">Label</label>
<input type="text" class="form-control form-control-lg rounded-pill" id="labelPhoto" th:field = "*{label}" placeholder="Enter label">
</div>
<div class="col">
<label for="photographer" class="col-sm-2 col-form-label col-form-label-lg">Photographer</label>
<input type="text" class="form-control form-control-lg rounded-pill" id="photographer" th:field = "*{photographer}" placeholder="Enter photographer">
</div>
</div>
<br/>
<div class="col-sm">
<button type="submit" class="btn btn-primary rounded-pill m-2 p-2 align-text-top">Submit</button>
</div>
</form>
</div>
</body>
</html>
I am passing the Event-ID through the GET and the POST-Endpoint of the Photo controller that I can assign there the Event to the photo. As far as I checked it the right ID arrives at "/photo/upload/{id}". I don't know why it seems there is no new photo created but instead the only existing gets altered since I don't reference the existing one when clicking on the upload button.
I have solved the problem.
Solution:
#PostMapping("/photo/upload/{id}")
public String uploadPhoto(#ModelAttribute ("photo") Photo photo, #PathVariable long id){
Photo newPhoto = new Photo();
newPhoto.setLabel(photo.getLabel());
newPhoto.setPhotographer(photo.getPhotographer());
photoService.assignEvent(newPhoto, id);
return "redirect:/";
}
I had to modify the PostMapping method. Creating there a new Photo object as well and assign the values from the Photo object I got from the form.
Related
I am building an event website using Springboot and I am trying to make the new_event page where you should create a new event. But aftetr completing the form and click the button "Add Event", there is nothing happening. What is the issue?
new_event HTML is:
<!DOCTYPE HTML>
<html xmlns:th="http://www.thymeleaf.org"
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
layout:decorate="~{layouts/default}">
<head>
<title>Create event</title>
</head>
<body>
<div layout:fragment="content">
<h1>Create a new event</h1>
<p> Complete the following fields to add an event . * - required field </p>
<form action="#" th:action="#{/events}" th:object="${events}" method="post">
<div class="form-group" th:classappend="${#fields.hasErrors('name')}? has-error">
<label for="name">Name *:</label>
<input class="form-control" type="text" th:field="*{name}" name="name" id="name" placeholder="Max 250 chars" autofocus="autofocus" required/>
<p class="text-danger" th:if="${#fields.hasErrors('name')}" th:errors="*{name}">errors</p>
<label for="ev_venue">Venue *:</label>
<input class="form-control" type="text" th:field="*{venue}" name="ev_venue" id="ev_venue" autofocus="autofocus" />
<label for="ev_date">Date *:</label>
<input class="form-control" type="date" th:field="*{date}" name="ev_date" id="ev_date" autofocus="autofocus" />
<label for="ev_time">Time :</label>
<input class="form-control" type="time" th:field="*{time}" name="ev_time" id="ev_time" autofocus="autofocus" />
<label for="ev_descr">Description :</label>
<input class="form-control" type="text" th:field="*{description}" name="ev_descr" id="ev_descr" placeholder="Max 500 chars" autofocus="autofocus" />
</div>
</form>
<button class="btn btn-primary" type="submit"><i class="fas fa-plus" aria-hidden="true"></i> Add Event</button>
<a class="btn btn-warning" role="button" href="/events"><i class="fas fa-ban" aria-hidden="true"></i> Cancel</a>
</form>
</div>
</body>
</html>
Event Controller is :
#Controller
#RequestMapping(value = "/events", produces = { MediaType.TEXT_HTML_VALUE })
public class EventsController {
#Autowired
private EventService eventService;
#GetMapping("/new_event")
public String newEvent(Model model) {
if (!model.containsAttribute("events")) {
model.addAttribute("events", new Event());
}
return "events/new_event";
}
#PostMapping(consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE)
public String createEvent(#RequestBody #Valid #ModelAttribute Event event, BindingResult errors,
Model model, RedirectAttributes redirectAttrs) {
if (errors.hasErrors()) {
model.addAttribute("events", event);
return "events/new_event";
}
eventService.save(event);
redirectAttrs.addFlashAttribute("ok_message", "New event added.");
return "redirect:/events";
}
}
EventController API is:
#RestController
#RequestMapping(value = "/api/events", produces = { MediaType.APPLICATION_JSON_VALUE, MediaTypes.HAL_JSON_VALUE })
public class EventsControllerApi {
private static final String NOT_FOUND_MSG = "{ \"error\": \"%s\", \"id\": %d }";
#Autowired
private EventService eventService;
#Autowired
private EventModelAssembler eventAssembler;
#GetMapping("/new_event")
public ResponseEntity<?> newEvent() {
return ResponseEntity.status(HttpStatus.NOT_ACCEPTABLE).build();
}
#PostMapping(consumes = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<?> createEvent(#RequestBody #Valid Event event, BindingResult result) {
if (result.hasErrors()) {
return ResponseEntity.unprocessableEntity().build();
}
Event newEvent = eventService.save(event);
EntityModel<Event> entity = eventAssembler.toModel(newEvent);
return ResponseEntity.created(entity.getRequiredLink(IanaLinkRelations.SELF).toUri()).build();
}
}
And the Event class:
#Entity
#Table(name = "events")
public class Event {
#Id
private long id;
#JsonFormat(shape = JsonFormat.Shape.STRING)
#DateTimeFormat(pattern = "yyyy-MM-dd")
private LocalDate date;
#JsonFormat(shape = JsonFormat.Shape.STRING)
#DateTimeFormat(pattern = "HH:mm")
private LocalTime time;
#Persistent
#NotEmpty(message = "The event must have a name.")
#Size(max = 250, message = "The name of the event must have 250 characters or less.")
private String name;
#ManyToOne
#Persistent
private Venue venue;
private String description;
public Event() {
}
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public LocalDate getDate() {
return date;
}
public void setDate(LocalDate date) {
this.date = date;
}
public LocalTime getTime() {
return time;
}
public void setTime(LocalTime time) {
this.time = time;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Venue getVenue() {
return venue;
}
public void setVenue(Venue venue) {
this.venue = venue;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
}
I am trying to pass in every form different objects and to different entities.
It is actually works, I can see the new added values(rows) in my database, but still I keep getting the same Exception by submitting both forms separately.
java.lang.IllegalStateException: Neither BindingResult nor plain target object for bean name 'post' available as request attribute
and
rg.thymeleaf.exceptions.TemplateProcessingException: Error during execution of processor 'org.thymeleaf.spring5.processor.SpringInputGeneralFieldTagProcessor' (template: "/addPost" - line 11, col 24)
my Controller
import com.example.blog.domain.Category;
import com.example.blog.domain.Post;
import com.example.blog.service.CategoryService;
import com.example.blog.service.PostService;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;
#Controller
#RequestMapping("edit")
public class EditController {
private final PostService postService;
private final CategoryService categoryService;
// At the same time, I can use #Autowired
public EditController(PostService postService , CategoryService categoryService) {
this.categoryService = categoryService;
this.postService = postService;
}
//(1)
#GetMapping("/addPost")
public String showAddPost(Model model) {
model.addAttribute("post", new Post());
model.addAttribute("category" , new Category());
return "/addPost";
}
//Mapping is coming from the view page(addPost.html).
//The name of the action must be equal
#PostMapping(value = "/upload")
public String dataPost(#ModelAttribute Post post, #RequestParam(value = "action", required = true) String action){
if (action.equals("AddPost")){
postService.addPost(post);
}
return "/addPost";
}
//default : show all posts
//and shows all categories
#GetMapping
public String showAllPosts(Model model){
model.addAttribute("posts",postService.getAllPosts());
model.addAttribute("categories" , categoryService.getAllCategories());
return "index";
}
#GetMapping("/deletePost/{id}")
public String deletePostById(#PathVariable("id") Long id){
postService.deletePost(id);
return "redirect:/edit";
}
#GetMapping("/editPost/{id}")
public String editPost(#PathVariable("id") Long id,Model model){
Post post = postService.findOnePost(id);
model.addAttribute("post", post);
return "updatePost";
}
#PostMapping("/updatePostAction/{id}")
public String updateEditedPost(#ModelAttribute Post post, #PathVariable Long id){
post.setId(id);
if (post.getId() == null){
throw new NullPointerException("what the hell: " + post.getId());
}
postService.EditPost(post);
return "redirect:/edit";
}
#PostMapping(value = "/addCategory" )
public String addCategory(#ModelAttribute Category category, #RequestParam(value = "action",required = true) String action) {
if (action.equals("AddCategory")) {
categoryService.addCategory(category);
}
return "/addPost";
}
and my html file:
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<form th:action="#{/edit/upload}" th:object="${post}" method="post" >
Name:<br>
<input type="text" th:field="*{author}">
<br>
Title:<br>
<input type="text" th:field="*{title}">
<br>
Post:<br>
<textarea name="post" id="" cols="30" rows="10" th:field="*{text}"></textarea>
<br><br>
<input type="submit" name="action" value="AddPost">
</form>
<br>
<form th:action="#{/edit/addCategory}" th:object="${category}" method="post" >
New Category: <br>
<input type="text" th:field="*{name}">
<input type="submit" name="action" value="AddCategory" >
</form>
<p th:text="${post.author}"></p>
<p th:text="${post.text}"></p>
</body>
</html>
How can I solve this Exception?
EDIT:
Post class.
#Entity
#Table(name = "posts")
public class Post {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private Date date;
private String author;
private String title;
private String text;
public Post(String author, String title, String text) {
this.author = author;
this.title = title;
this.text = text;
}
public Post(){
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public Date getDate() {
return date;
}
public void setDate(Date date) {
this.date = date;
}
public String getAuthor() {
return author;
}
public void setAuthor(String author) {
this.author = author;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getText() {
return text;
}
public void setText(String text) {
this.text = text;
}
}
I have an customer object whose fields I'm trying to access in my view with Thymeleaf. I've used the usual syntax i.e:
<p th:text="${customer.name}"></p>
however, this does not work, it does work when I use the get() method i.e:
<p th:text="${customer.get.name}"></p>
Any idea why that is happening? I'm just getting started with Thymeleaf, so I apologize in advance if this is a dumb question.
Here's my Model:
#Id
#GeneratedValue
private int id;
#NotNull
#Size(min = 2, message="Company name length must be at least 1 character long.")
private String name;
public Customer() {}
public Customer(String name) {
this.name = name;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
And the Controller:
#RequestMapping("")
public String index(Model model) {
model.addAttribute("title", "Home");
model.addAttribute("customers", customerDao.findAllByOrderByNameAsc());
return "index";
}
#RequestMapping(value = "", method = RequestMethod.POST)
public String processFetch(#ModelAttribute Customer customer, Model model) {
model.addAttribute("title", "Home");
model.addAttribute("customers", customerDao.findAllByOrderByNameAsc());
model.addAttribute("c", customerDao.findById(customer.getId()));
return "index";
}
and the View:
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org/">
<head th:replace="fragments::head"></head>
<body>
<nav th:replace="fragments::nav"></nav>
<div class="container">
<h1 class="title" th:text="${title}"></h1>
</div>
<div style="text-align: center">
<form method="post" th:object="${customers}" style="display: block;margin: 0 auto;width:300px;margin-top:5%">
<select class="form-control" name="customer">
<option style="text-align:center" th:each="customer:${customers}" th:value="${customer.id}" th:text="${customer.name}"></option>
</select>
<input class="button" style="display:block;margin:0 auto;margin-top:30px" type="submit" value="Fetch" />
</form>
</div>
<div>
<h1 th:text="${c.get().name}"></h1>
</div>
</body>
</html>
Here's my Repository class:
public interface CustomerDao extends CrudRepository<Customer, Integer> {
public Iterable<Customer> findAllByOrderByNameAsc();
}
The error I try to submit the form is:
Caused by: org.springframework.expression.spel.SpelEvaluationException: EL1007E: Property or field 'name' cannot be found on null
I'm not sure why it cannot find property 'name'. It should be part of the object.
I appreciate any insight into this!
I am sending JSON object to a Spring+Hibernate+MySQL application.
Bellow is index.html where you can see the javascript making the request. Then there is Customer.java entity and CustomerRestController.java responsible for the request processing. Somehow my database is not getting updated.
<!DOCTYPE html>
<html lang="en">
<head>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script>
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<script type="text/javascript">
$(document).ready(function(){
$('#btnBooking').click(function(){
var custName=$('#userName').val();
var custAddress=$('#address1').val();
var JSONObject= {"name":custName, "address":custAddress};
//var jsonData = JSON.stringify( JSONObject );
$.ajax({
type: "POST",
url: "http://192.168.1.12:8080/HomeServiceProvider/rest/customer/saveCustomer",
data: JSON.stringify( JSONObject ),
dataType: "json",
processData: true,
contentType: "application/json; charset=utf-8",
success: function(data, status, jqXHR){
alert("success..."+data);
},
error: function(xhr){
alert("error"+xhr.responseText);
}
});
});
});
</script>
</head>
<body>
<form class="form-horizontal" id="scheduleLaterForm" name="scheduleLaterForm" action="#" method="post">
<div class="col-lg-8">
<div class="form-group">
<label class="col-lg-3 control-label">Name:<font style="color: red;">*</font></label>
<div class="col-lg-9">
<input class="form-control" id="userName" name="userName" placeholder="Full Name" value="" type="text">
</div>
</div>
<div class="form-group">
<label class="col-lg-3 control-label">Address:<font style="color: red;">*</font></label>
<div class="col-lg-9">
<input class="form-control" name="address1" id="address1" placeholder="Full address" value="" type="text">
</div>
</div>
<div class="form-group marg-bot-45">
<label class="col-lg-3 control-label"></label>
<div class="col-lg-9">
<button type="button" class="btn btn-info" id="btnBooking"> Confirm Booking </button>
</div>
</div>
</div>
</form>
</body>
</html>
Customer.java
#Entity
#Table(name="CUSTOMER")
public class Customer implements Serializable{
private static final long serialVersionUID = -82689141527424144L;
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column (name="CUST_ID")
private int custId;
#Column (name="NAME")
private String name;
#Column (name="ADDRESS")
private String address;
public int getCustId() {
return custId;
}
public void setCustId(int custId) {
this.custId = custId;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
}
CustomerRestController.java
#RestController
#RequestMapping("/customer")
public class CustomerRestController {
private static Logger log = LogManager.getLogger(CustomerRestController.class);
#Value("${msg.customeradded}")
private String message;
#Value("${msg.successcode}")
private int code;
#Autowired
private CustomerService customerService;
#RequestMapping(value = "/saveCustomer", method = RequestMethod.POST, consumes = MediaType.APPLICATION_JSON_VALUE)
public #ResponseBody Status saveCustomer(#RequestBody Customer customer){
try {
customerService.saveCustomer(customer);
return new Status(code, message);
} catch (Exception e) {
return new Status(0, e.toString());
}
}
#RequestMapping(value="/getAllCustomer",method=RequestMethod.GET, headers="Accept=application/json")
public #ResponseBody List<Customer> getAllCustomer(){
List<Customer> customers = null;
try {
customers = customerService.getAllCustomer();
log.info("Size:"+customers.size());
log.info("customers:"+customers);
} catch(Exception e) {
e.printStackTrace();
}
return customers;
}
}
CustomerService.java
public interface CustomerService {
public void saveCustomer(Customer customer);
public List<Customer> getAllCustomer();
}
CustomerServiceImpl.java
#Service
public class CustomerServiceImpl implements CustomerService {
private static Logger log = LogManager.getLogger(CustomerServiceImpl.class);
#Autowired
private CustomerDao customerDao;
public void saveCustomer(Customer customer) {
log.info("customer first name:" + customer.getCustName());
customerDao.saveCustomer(customer);
}
public List<Customer> getAllCustomer() {
List<Customer> customers = customerDao.getAllCustomer();
log.info("Size:"+customers.size());
log.info("customers:"+customers);
return customers;
}
}
Name of My table is CUSTOMER and columns are
colomn1: CUST_ID
colomn2: NAME
colomn3: ADDRESS
I'm currently working on a group project where we're supposed to handle the relation between Building and Room. The relation is OnetoMany, and we're currently able to show the relevant data from sql, but we're not able to display it in a good looking spreadsheet or table as intended. We would like to have the buildings and room sorted into a table, where each room shows connection to related building. How do we put our the HTML code in our (ShowRooms.jsp) jsp to get all rooms for building of choice by user, and then display all rooms by that building in a good-looking-table? In this state we get the data from our sql-database but just in a straight line instead of by a table which connects each room to the relevant building. Thanks in advance!
This is our code: BUILDING:
#Entity
#Table(name = "Building")
public class Building {
private String bname;
private List<Room> rooms; // Building can have many Rooms
#Id
#Column(name = "Bname")
public String getBname() {
return bname;
}
public void setBname(String bname) {
this.bname = bname;
}
#OneToMany(mappedBy = "building", fetch = FetchType.EAGER)
public List<Room> getRooms() {
return rooms;
}
public void setRooms(List<Room> rooms) {
this.rooms = rooms;
}
}
ROOM:
#NamedQueries({
#NamedQuery(name="Room.findByBname",
query="SELECT r FROM Room r WHERE r.bname LIKE :bname"),
})
#Entity
#Table(name = "Room")
public class Room implements Serializable {
/**
*
*/
private static final long serialVersionUID = 1L;
private RoomId id;
private String bname;
private Building building;
public String getBname() {
return bname;
}
public void setBname(String bname) {
this.bname = bname;
}
#Id
public RoomId getId() {
return id;
}
public void setId(RoomId id) {
this.id = id;
}
#ManyToOne
#JoinColumn(name = "Bname", insertable = false, updatable = false)
public Building getBuilding() {
return this.building;
}
public void setBuilding(Building building) {
this.building = building;
}
}
ROOMID:
#Embeddable
public class RoomId implements Serializable {
private String bname;
private String rcode;
public RoomId() {
}
public RoomId(String bname, String rcode) {
this.bname = bname;
this.rcode = rcode;
}
#Column(name = "Bname", nullable = false)
public String getbname() {
return bname;
}
public void setbname(String bname) {
this.bname = bname;
}
#Column(name = "Rcode", nullable = false)
public String getrcode() {
return rcode;
}
public void setrcode(String rcode) {
this.rcode = rcode;
}
public boolean equals(Object other) {
if ((this == other)) {
return true;
}
if ((other == null)) {
return false;
}
if (!(other instanceof RoomId)) {
return false;
}
RoomId castOther = (RoomId) other;
return ((this.getbname() == castOther.getbname()) || (this.getbname() != null
&& castOther.getbname() != null &&
this.getbname().equals(castOther.getbname())))
&&
((this.getrcode() == castOther.getrcode()) || (this.getrcode() != null && castOther.getrcode() != null &&
this.getrcode().equals(castOther.getrcode())));
}
public int hashCode() {
return super.hashCode();
}
}
BUILDINGEAO:
#Stateless
public class BuildingEAOImpl implements BuildingEAOImplLocal {
#PersistenceContext(unitName = "LabEJBSql")
private EntityManager em;
public BuildingEAOImpl() {
// TODO Auto-generated constructor stub
}
public Building findByBname(String bname) {
return em.find(Building.class, bname);
}
}
FACADE:
#Stateless
public class Facade implements FacadeRemote, FacadeLocal {
#EJB
BuildingEAOImplLocal BuildingEAO;
#EJB
RoomEAOImplLocal RoomEAO;
public Facade() {
// TODO Auto-generated constructor stub
}
public List<Room> findRoomsByBname(String bname) {
return RoomEAO.findByBname(bname);
}
}
SERVLET:
#WebServlet("/TestClientServlet")
public class TestClientServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
#EJB
private FacadeLocal facade;
/**
* #see HttpServlet#HttpServlet()
*/
public TestClientServlet() {
super();
// TODO Auto-generated constructor stub
}
protected void doGet(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
PrintWriter out = response.getWriter();
out.println("TestClientServlet-doGet");
out.close();
}
protected void doPost(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
String url = null;
// Get hidden field
String operation = request.getParameter("operation");
if (operation.equals("showrooms")) {
String bname = request.getParameter("txtBname");
List<Room> r = facade.findRoomsByBname(bname);
request.setAttribute("rooms", r);
url = "/ShowRooms.jsp";
} else if (operation.equals("searchbuilding")) {
System.out.println("TestClientServlet-searchbuilding");
url = "/SearchBuilding.jsp";
} else {
url = "/SearchBuilding.jsp";
}
System.out.println(url);
RequestDispatcher dispatcher = getServletContext()
.getRequestDispatcher(url);
dispatcher.forward(request, response);
}
*/
}
SEARCHBUILDING.JSP:
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-
8859-1">
<title>Search Building</title>
</head>
<body>
<form action="/BuildRoomClientProject/TestClientServlet" method="post">
<table cellspacing="0" cellpadding="0" border="0" align="left">
<tr>
<td><h2>Search Building:</h2></td>
</tr>
<tr>
<td>
<input type= "text" name= "txtBname" size ="25" maxlength="25">
<input type="submit" name="submit" value="Search" />
</td>
<td></td>
</tr>
</table>
<input name="operation" value="showrooms" type="hidden">
</form>
</body>
</html>
SHOWROOMS.JSP:
<%# page contentType="text/html;charset=windows-1252"%>
<%# page import = "org.ics.ejb.Building" %>
<%# page import = "org.ics.ejb.Room" %>
<%# page import = "org.ics.ejb.RoomId" %>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>
Show Rooms
</title>
</head>
<body>
<h2>
Rooms:
</h2>
<%List<Room> r = (List<Room>)request.getAttribute("rooms"); %>
<% for (Room r1 : r){
out.println(r1.getBname() + " " + r1.getId().getrcode());
}%>
<p>
</p>
<form action="/BuildRoomClientProject/TestClientServlet" method="post">
<input type="submit" name="submit" value="Tillbaka">
<input name="operation" value="searchbuilding" type="hidden">
</form>
</body>
</html>
For your jpql, youldn't you use a GROUPBY combined with a GROUPBY directive?
Then for each table entry that is one you get render the bname (= BuildingName ??) as first row.
Then render your retrieved list as a table, a short example could be somehow this:
<table>
<c:forEach var="o" items="${objects}">
<tr>
<td>${o.bname}</td>
<td>${o.id}</td>
<td>${o.name}</td>
<td>${o.descriptio}</td>
</tr>
</c:forEach>
</table>
In fact, I just found this: displaying a list of entities in jsp file by using java searching for "jsp, listview, table"