I need to manually display data from database in jsp page. But it wont display.
My entity:
#Entity
#NamedQuery(name="Contact.getAll", query="SELECT c FROM Contact c")
public class Contact implements Serializable {
private static final long serialVersionUID = 1L;
#Id
private String login;
private String name;
private String surname;
getters/setters/equals/hashcode
Bean to manage jsp:
public class DisplayDataBean {
private EntityManagerFactory emf = Persistence.createEntityManagerFactory("ContactsPU");
private EntityManager em = emf.createEntityManager();
private List<Contact> contacts = em.createNamedQuery("Contact.getAll", Contact.class).getResultList();
public List<Contact> getContacts() {
return contacts;
}
}
And jsp page fragment:
<c:forEach var="contact" items="${DisplayDataBean.contacts}">
<tr>
<td><c:out value="${contact.login}"/></td>
<td><c:out value="${contact.name}"/></td>
<td><c:out value="${contact.surname}"/></td>
</tr>
</c:forEach>
Can you please tell what can be wrong in here? Thanks in advance.
Also when i work with
<sql:query var="contacts" dataSource="jdbc/contactapplication">
SELECT * FROM contact;
</sql:query>
everything is fine.
Problem was that i didnt declare DisplayDataBean.
Solution is to add tag in jsp page:
<jsp:useBean id="displayBean" class="web.DisplayDataBean"/>
You are not declaring the variable contacts so that it is not showing, when you are using JSTL tag then you are using variable contacts.
I you are using Spring then please add this contacts variable to ModelMap so that it can be retrieve.
ModelMap mm = new ModelMap();
mm.put("contacts", values);
Or if you are using Servlet then just add this variable to response parameter.
request.setAttribute("contacts", "value");
You may have to provide a physical table name to your entity. I think case sensitivity may cause problems here ("contact" and "Contact" aren't necessarily considered the same).
Also, I'm not 100% sure, but the #NamedQuery may need to be enclosed into #NamedQueries - so the entity definition could start like this:
#Entity
#Table(name="contact")
#NamedQueries({
#NamedQuery(name="Contact.getAll", query="SELECT c FROM Contact c")
})
public class Contact implements Serializable {
// the rest of the class definition goes here...
If you have debugging enabled, you may be able to see if the query was actually issued or if it "failed" even before that.
By the way, when you say "it won't display", does it mean nothing is rendered by c:forEach? Does it render empty table, nulls or nothing at all? Example of the generated output could help.
I assume there are no exceptions visible in the console/log?
Related
I have a list of Albums that have a list of Tracks that have a list of Artists. I want to get all artists involved in making tracks for each Album.
If I have one Album, I can pass that Album to a method Controller, get the list of Artists with Java streams and pass it to EL in .jsp file.
But I have a list of Albums that I iterate through in c:forEach and I want to do get list of Artists in each iteration. I tried to do it with EL, but Java 8 Streams are not supported in EL. Is there another way to do this?
Excerpt from Album.
#Entity
#Table(name="album")
#NamedQuery(name="Album.findAll", query="SELECT a FROM Album a")
public class Album implements Serializable {
//bi-directional many-to-one association to Track
#OneToMany(mappedBy="album")
private List<Track> tracks;
public List<Track> getTracks() {
return this.tracks;
}
}
Except from Track.
#Entity
#Table(name="track")
#NamedQuery(name="Track.findAll", query="SELECT t FROM Track t")
public class Track implements Serializable {
//bi-directional many-to-one association to Album
#ManyToOne
#JoinColumn(name="albumid")
private Album album;
//bi-directional many-to-many association to Artist
#ManyToMany
#JoinTable(
name="producestracks"
, joinColumns={
#JoinColumn(name="trackid")
}
, inverseJoinColumns={
#JoinColumn(name="artistid")
}
)
private List<Artist> artists;
public Album getAlbum() {
return this.album;
}
public List<Artist> getArtists() {
return this.artists;
}
}
Excerpt from jsp file.
<table border="1">
<tr>
<th>Artists</th>
</tr>
<c:forEach items="${allalbums }" var="a">
<tr>
<td>
<!-- THIS DOES NOT WORK HERE!!! -->
<c:set var="ars" value="${a.tracks.stream()
.flatMap(t -> t.getArtists().stream())
.distinct()
.collect(Collectors.toList()) }"/>
<c:forEach items="${ars }" var="ar" varStatus="loop">
${ar.name}
<c:if test="${!loop.last}">, </c:if>
</c:forEach>
</td>
</tr>
</c:forEach>
</table>
Excerpt from AlbumController.
#RequestMapping(value = "/getTracks", method = RequestMethod.GET)
public String getTracks(HttpServletRequest request) {
List<Track> ts = tr.findAll();
request.getSession().setAttribute("alltracks", ts);
return "view/viewtracks";
}
No, you can't use streams in jsp. You have two options here:
Do the loop in a traditional way in jsp. The same way you would have done it prior to java 8 streams. Even this is difficult due to the nature of the loop you need, that implies data manipulation. JSP is a presentation techonology, very read-only focused (except for simple variable assignment). You could create a Set with <jsp:useBean> but you would'n have a clean way to add elements to it.
Create a method that returns this for you and call it from jsp:
return a.tracks.stream()
.flatMap(t -> t.getArtists().stream())
.distinct()
.collect(Collectors.toList());
You may have the temptation to create this method directly in the entity class, but I would advice against this. Keep the entity for the entity purpose, and use a Helper class to provide supporting functions to use in jsp.
I'm trying to learn Spring and other related technologies during summer break by developing a simple web application, however Thymeleaf hinders my progress.
The program is based on two entity classes:
Invoice.java:
#Entity
public class Invoice {
#Id
private String invoiceId;
#NotNull
#DateTimeFormat(pattern = "yyyy-MM-dd")
private LocalDate issueDate;
//getters and setters
}
TrasportOrder.java:
#Entity
public class TransportOrder {
#Id
private int number;
#NotNull
private BigDecimal value;
#ManyToOne
private Invoice invoice;
//getters and setters
}
I'm getting a form for adding invoices using a method from InvoiceController:
#GetMapping(path = "/add")
public String getForm(Model model) {
model.addAttribute("unusedOrders", service.getInvoiceOrders(null));
model.addAttribute("orders", new ArrayList<TransportOrder>());
model.addAttribute("invoice", new Invoice());
return "addInvoice";
}
unusedOrders is a list of orders that a user can choose from,
orders is a list that is meant to contain orders chosen by user
invoice is just an invoice that's being created in the form.
My form contains text and data inputs regarding the invoice, and then comes a multiple select for the orders:
<!-- I used to define th:object here and used th:field in the inputs, however changed it to use th:value everywhere -->
<form action="/invoices/add" method="post">
<table>
<tr>
<th>
Invoice ID:
</th>
<th>
<input type="text" th:value="${invoice.invoiceId}" name="invoiceId"/>
</th>
</tr>
<tr>
<!-- a few other inputs -->
</tr>
<tr>
<th>
Orders:
</th>
<th>
<!-- problem may lie here -->
<select id="orders" th:value="${orders}" multiple="multiple">
<option th:each="unusedOrder: ${unusedOrders}"
th:value="${unusedOrder.number}"
th:text="${unusedOrder}">Unused orders to choose from</option>
</select>
</th>
</tr>
</table>
<button type="submit">Next</button>
</form>
I've read Thymeleaf docs and forums, as well as several SO questions, but they still leave me confused about how does th:object, th:field, th:value and others work with forms, and especially with multiple select tag.
On submit, the form sends a POST request to a method in the same controller:
#PostMapping(path = "/add")
public String addInvoice(#ModelAttribute Invoice invoice,
BindingResult result,
#ModelAttribute("orders") ArrayList<TransportOrder> orders,
Model model) {
//invoice and orders saving logic, etc.
return "viewInvoices";
}
My problem is that invoice is being properly retrieved from the from and persisted in the database, but orders list stays empty. I expect it to be populated with orders chosen in the form. I don't know, if it's because of #ModelAttribute annotation (I also tried #RequestAttribute without success), Thymeleaf tags, or anything else.
Okay, so I decided to fight for the answer once more, and fortunately I stumbled upon an answer.
Based on this tutorial, I created an wrapper class ChosenOrdersDTO:
public class ChosenOrdersDTO {
private List<TransportOrder> chosenOrders;
//constructor, getters, setters...
}
I added it to the first model (changed the getForm() method as following):
model.addAttribute("chosenOrders", new ChosenOrdersDTO(new ArrayList<>()));
In the form I used the th:field tag, similarly to previous fields:
<select id="orders" th:field="${chosenOrders.chosenOrders}" multiple="multiple">
And in the second controller I was able to retrieve the list wrapped in the ChosenOrdersDTO class as a #ModelAttribute:
#PostMapping(path = "/add")
public String addInvoice(#ModelAttribute Invoice invoice,
BindingResult
#ModelAttribute ChosenOrdersDTO chosenOrders,
Model model)
I'm working in the Spring Framework. How do I pass object variable values into the Hibernate criteria restriction?
This is how I've written them:
#Repository
public class EventSearchDAOImpl implements EventSearchDAO<Event> {
#Autowired
private SessionFactory sessionFactory;
private Session session;
private Transaction trans;
#Override
public List<Event> getAll(Event event) {
session = sessionFactory.openSession();
System.out.println(event.getType()+event.getName());
return session.createCriteria(Event.class).add(Restrictions
.and(Restrictions.like("type", "%"+event.getType()+"%"),
Restrictions.like("name", "%"+event.getName()+"%")))
.list();
}
}
I printed the values in my output console to check via System.out.println(event.getType()+event.getName()); and they do seem to get passed successfully.
This is how I'm passing them via my DefaultController.java class:
#RequestMapping(value = "/searchEvent", method = RequestMethod.POST)
public String searchEvent(Event event, Model model) {
Event e = new Event();
e.setType(event.getType());
e.setName(event.getName());
model.addAttribute("check", eventSearchDAO.getAll(e));
return "redirect:/";
}
A form in my index.jsp page posts data into the above line of code.
To check if the code works, I added the following bit in my index.jsp:
<c:forEach var="i" items="${check}">
${i.name} || ${i.type} <br>
</c:forEach>
If I manually write the restrictions as
return session.createCriteria(Event.class).add(Restrictions
.and(Restrictions.like("type", "%fair%"),
Restrictions.like("name", "%auto%")))
.list();
and make a few tweaks in the controller accordingly, it works just fine. But when I do it by passing the object's variables, it doesn't seem to work. That's my problem. Please help me fix this.
Turns out there was a mistake in my Controller class DefaultController.java, I should've wrote:
return "index";
instead of:
return "redirect:/";
Yes, I'm an idiot.
Hello fellow programmers,
I am writing a Spring MVC application for students to do an online assessment with multiple choice questions. An admin should be able to create assessments, so I created this object structure:
#Entity
#Table(name = "assessment")
public class Assessment {
private List<Question> questions;
// getter and setter
}
#Entity
#Table(name = "question")
public class Question {
private String questionText;
private List<Answer> answers;
// getters and setters
}
#Entity
#Table(name = "answer")
public class Answer {
private String answerText;
private boolean isCorrect;
// getters and setters
}
Now, I am using a JSP form on the admin page:
Controller
#RequestMapping(value = "/add/assessment", method = RequestMethod.GET)
public String addAssessments(Model model) {
model.addAttribute("assessmentModel", new Assessment());
return "admin-assessments-create";
}
JSP form
<form:form method="POST" modelAttribute="assessmentModel">
<form:input path="questions[0].questionText" type="text"/> <!-- this is working-->
<form:radiobutton path="questions[0].answers[0].isCorrect"/> <!-- not working-->
<form:input path="questions[0].answers[0].answerText"/>
<button class="btn" type="submit">Submit</button>
</form:form>
When I go to this page I receive the following error:
org.springframework.beans.NotReadablePropertyException:
Invalid property 'questions[0].answers[0].isCorrect' of bean class [com.johndoe.model.Question]:
Bean property 'questions[0].answers[0].isCorrect' is not readable or has an invalid getter method:
Does the return type of the getter match the parameter type of the setter?
I checked all the getters and setters but those are perfectly fine.
Question:
how do I avoid the NotReadablePropertyException and thus bind the nested Answer List to my form?
Use
<form:radiobutton path="questions[0].answers[0].correct"/>
and it will be working.
Why? For boolean fields you have to adapt the get/set paradigm to "is"XYZ(). For the EL expression, you have to drop the "is" in front of the method that accesses the current value of the field, pretty much the same way, you would do with "get" / "set".
I`m trying to retrieve only entries(posts) which possess a specific tag. One entry can have many tags, so I use List of objects. But I don't know how to construct a proper command in Controller class, actually I'm afraid I’m completely lost here.
Entry entity looks like this:
#Entity
public class BlogEntry {
#Id
#GeneratedValue
private Integer id;
private String title;
#Column(name = "published_date")
private Date publishedDate;
#ManyToMany
#JoinTable
private List<TagBlog> blogTags; /* Multiple tags to one entry */
And my Tag entity:
#Entity
public class TagBlog {
#Id
#GeneratedValue
private Integer id;
private String tag;
#ManyToMany(mappedBy="blogTags")
private List<BlogEntry> entries;
In my EntryService class I wanted to perform this kind of sort "findByTagBlogIn" which I wish would return List of posts that possess specific tag.
public List<BlogEntry> findAllByTags(List<TagBlog> tag){
List<BlogEntry> blogEntry = entryRepository.findByTagBlogIn(tag);
return blogEntry;
}
But I don't know how to refer to it in Controller class. How can I retrieve only entries with specific tag? Something like this? But how to pass List of tags as a parameter, maybe it should be String?
#RequestMapping(value="/welcome")
public String retrieveTaggedEntry(Model model, ?List of tags?){
model.addAttribute("entriesWithTag", entryService.findAllByTags(TagBlog tag));
return "redirect:/welcome.html";
}
In the welcome.jsp file I would like to iterate throught whole List of tags that had been assigned to specific entry(post) like in example below (between the arrows "---> <---" is the part of my conserns):
<c:forEach items="${entries}" var="entry"> <!--"entries" refers to List of BlogEntry-->
<table>
<tr>
<td>Entry No. ${entry.id }</td>
<td>${entry.title}</td>
<td>
Tags: ---> #${entry.? blogTag.tag ?}, <---
</td>
<td>Published: ${entry.publishedDate}</td>
<td>
<spring:url value="/delete_entry/${entry.id}.html" var="url" />
Delete
</td>
</tr>
</table>
</c:forEach>
By working it out later, I want to perform a sort (by mapping spring:url value="/tag/${some_tag_as_a_String}.html") by entries that possess a specific tag.
Maybe there is an easier way to return posts only with specific tag? But I guess it would be easier for me to work with what I got here. Anyway, any solution provided is appreciated.
I'm willing to add any additional information if needed.
Is there any reason you want to send the whole TagBlog object to the Controller? Why not just the tag ID or tag text? E.g.
#RequestMapping(value="/welcome")
public String retrieveTaggedEntry(Model model, #RequestParam List<String> tags) {
// Do something with your tags
}