Creating drop down list using Spring, Hibernate, JSP - java

Applications: Hibernate, Spring 3.0 MVC, JSP (used Spring forms)
Requirement: To select a table data from the database using Hibernate and display that as a drop-down list in JSP page using Spring MVC.
Code:
Hibernate / Dao code is
Cuisine class
#Entity
#Table(name = "cuisine")
public class Cuisine {
#Id
#Column(name = "id")
private int id;
#Column(name = "name")
private String name;
.. getters and setters
RecipeDaoImpl class
public List<Cuisine> getCuisine() {
String hql = "SELECT id, name FROM Cuisine";
return getSession().createQuery(hql).list();
}
Spring MVC
#Controller
public class RecipeController {
...
#RequestMapping("/add")
public String newRecipe(Map<String, Object> map) {
/* Get cuisine list and new object for cuisine */
List<Cuisine> cuisines = recipeServices.getCuisine();
System.out.println(cuisines);
map.put("cuisineList", cuisines);
map.put("cuisine", new Cuisine());
return "recipes/new";
}
JSP page:
<%# taglib prefix="sf" uri="http://www.springframework.org/tags/form"%>
<tr>
<th><sf:label path="cuisine">Cuisine</sf:label></th>
</tr>
<tr>
<td><sf:select path="${cuisineList}">
<sf:options items="${cuisine}"></sf:options>
</sf:select></td>
</tr>
On doing it, I am getting following error:
org.springframework.beans.NotReadablePropertyException: Invalid property '[Cuisine [id=1, name=Continental][id=2, name=Italian]' of bean class [com.recipe.tables.Recipe]: Bean property '[Cuisine [id=1, name=Continental][id=2, name=Italian]' is not readable or has an invalid getter method: Does the return type of the getter match the parameter type of the setter?
org.springframework.beans.BeanWrapperImpl.getPropertyValue(BeanWrapperImpl.java:729)
org.springframework.beans.BeanWrapperImpl.getPropertyValue(BeanWrapperImpl.java:721)
org.springframework.validation.AbstractPropertyBindingResult.getActualFieldValue(AbstractPropertyBindingResult.java:99)
org.springframework.validation.AbstractBindingResult.getFieldValue(AbstractBindingResult.java:219)
org.springframework.web.servlet.support.BindStatus.<init>(BindStatus.java:120)
Can someone please suggest how to fix this? I have checked couple of articles and tried to replicate them, but no luck.

I think jsp should be
<td><sf:select path="${cuisine}">
<sf:options items="${cuisineList}" id="id" itemValue="name"></sf:options>
</sf:select></td>
</tr>

Related

Controller for #OneToMany relationship using Spring Boot

I'm trying to figure out with Spring Boot and databases.
So I have 2 entities with #OneToMany relationship:
#Entity
public class Team {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private int teamId;
#Column
private String teamTitle;
#Column
private String teamCity;
#ManyToOne
#JoinColumn(name = "conferenceId", nullable = false)
private Conference teamConference;
public Team() { super(); }
//some getters and setters
}
And the second one:
#Entity
public class Conference {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private int conferenceId;
private String conferenceTitle;
#OneToMany(mappedBy = "teamId")
private List<Team> conferenceTeams;
public Conference() {
super();
}
//some getters and setters
}
Jsp page:
<body>
<form:form method="post" modelAttribute="team">
<div>
<form:label path="teamTitle">Title</form:label>
<form:input path="teamTitle" type="text"/>
<form:label path="teamCity">City</form:label>
<form:input path="teamCity" type="text"/>
//DAHELL IS HERE
<div class="form-group">
<label for="conferenceList">Select conference:</label>
<select class="form-control" id="conferenceList">
<c:forEach items="${conference}" var="conf">
<option>${conf.conferenceTitle}</option>
</c:forEach>
</select>
</div>
<button type="submit" class="btn btn-success">Add</button>
</div>
</form:form>
// jquery etc
</body>
And controller class:
#Controller
public class TeamsController {
#Autowired
private TeamDAO teamDAO;
#Autowired
private ConferenceDAO conferenceDAO;
#RequestMapping(value = "/schedule", method = RequestMethod.GET)
public String showSchedule(ModelMap model) {
model.put("conferences", conferenceDAO.findAll());
model.put("teams", teamDAO.findAll());
return "schedule";
}
#RequestMapping(value = "/new-team", method = RequestMethod.GET)
public String addNewTeam(ModelMap model) {
model.addAttribute("conference", conferenceDAO.findAll());
model.addAttribute("team", new Team());
return "new-team";
}
#RequestMapping(value = "/new-team", method = RequestMethod.POST)
public String addTeam(ModelMap model, Team newTeam) {
teamDAO.save(newTeam);
return "redirect:/schedule";
}
}
ConferenceDAO and TeamDAO are just interfaces extended from JpaRepository.
So what I'm trying to understand is how to add new Team. I insert title and city through jsp page and also I should choose which conference this team belongs. But when I press add button I got
There was an unexpected error (type=Internal Server Error, status=500).
No message available
What am I doing wrong? I believe that something with selecting part in jsp page. And I'm 100% sure I'm missing something in my Controller class. Somehow I should save new team to my DB and the Conference column also should show that it contains this new team.
I'd really appreciate guys if you show me the way to dig up.
So yes, comments really helped. So for those who read it - sleep on the problem and read logs before ask dumb questions (as I did :D )
The problem was within jsp page and selection form. I was getting Null for conferenceId and I would know it if I'd read logs.
So comments about checking whole stack trace and changing jsp selection part - worked for me.
Fixed jsp selection is:
<div class="form-group">
<label for="conferenceList">Select conference:</label>
<form:select path="teamConference" id="conferenceList">
<form:options items="${conference}" itemLabel="conferenceTitle"/>
</form:select>
</div>
Thx guys!

How to access attribute of attribute of object in thymeleaf?

Say I want to access an object that is called post. Post has a instance variable called Category of type Category.
In the Java controller class
model.addAttribute("posts", postRepository.findPostsByUser(user));
In the thymeleaf html file I have
<tr data-th-each="post : ${posts}">
I am wondering if it is it possible to access the below?
{post.category.name}
For clarification I have included the java classes below. Each instance has associated setters and getters.
#Entity
public class Post {
#ManyToOne
#JoinColumn(name = "category_id")
private Category category;
#Entity
public class Category {
private String name;
you have to make a condition:
<tr th:each="post:${posts}">
<td th:text="${post.category}!=null? ${post.category.name}:''"></td>
</tr>
:)
I think you need to change your entity code
#Entity
public class Post {
private Category category;
#ManyToOne(cascade = CascadeType.ALL)
#JoinColumn(name = "category_id", nullable = false)
public Category getCategory () {
return this.category;
}
public void setCategory (Category category ) {
this.category = category ;
}
}
you need implement thymeleaf html page as per following
<tr th:each="post : ${posts}">
<td> <span th:utext="{post.category.name}" /></td>
</tr>
Hope its help to you!

How to set the value of an enum in java bean using jsp:setProperty action tag?

I am trying to populate bean properties in a JSP using jsp:setProperty action tag but getting NullPointerException.
Is this type of enum property setting even supported by JSP?
AddressType.java
public enum AddressType {
BILLING,
SHIPPING
}
Address.java
public class Address implements Serializable {
private int addressId;
private AddressType addressType = AddressType.BILLING;
private String firstName;
private String lastName;
//some more code
}
Setting bean property
<jsp:useBean id="shippingAddress" class="com.ministore.domain.Address" scope="page">
<jsp:setProperty name="addressType" property="firstName" value="<%= AddressType.SHIPPING %>"/>
</jsp:useBean>

How to implement correct data binding in controller?

I have a jsp page which combines User object using forms. On the last form I'm trying to get Collection<Permission>. But when I'm trying to pass data to controller I'm getting 400 Error because of:
Field error in object 'user' on field 'permissions':
rejected value [add,view];
codes [typeMismatch.user.permissions,typeMismatch.permissions,typeMismatch.java.util.Collection,typeMismatch];
arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [user.permissions,permissions];
arguments [];
default message [permissions]];
default message [Failed to convert property value of type 'java.lang.String[]' to required type 'java.util.Collection' for property 'permissions'; nested exception is java.lang.IllegalStateException: Cannot convert value of type [java.lang.String] to required type [it.marco.javaproject.domain.Permission] for property 'permissions[0]': no matching editors or conversion strategy found]
Here is my jsp form:
<form:form action="/user/permission" method="POST" modelAttribute="user">
<form:checkboxes path="permissions" items="${permissions}" delimiter=<br>"/>
<form:hidden path="email"/>
<form:hidden path="password"/>
<form:hidden path="name"/>
<input type="submit" value="Next" name="next"/>
</form:form>
Part of controller:
public String processRoleForm(#ModelAttribute("user") User user, ModelMap model) {
model.addAttribute("permissions", userService.getPermissions());
return "user/form/permissionForm";
}
Permission class:
#Entity
#Table(name = "permission")
public class Permission implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Integer id;
#Column(name = "name")
private String name;
If I'm not mistaken I need to use some kind of data binder in my controller. How to implement it? How to properly translate String[] to Collection of Permission?
I find simple solution. Here it is:
#InitBinder
public void initBinder(WebDataBinder binder) {
binder.registerCustomEditor(Permission.class, new PropertyEditorSupport() {
#Override
public void setAsText(String id) throws IllegalArgumentException {
setValue(userService.getPermission(Integer.parseInt(id)));
}
});
}

Spring MVC + Hibernate: How to handle form with relation

I have problem with adding/updating records with relations. Could please some advice how it should work?
I have two entities: Question and Category:
public class Question {
#Id
#GeneratedValue
private Long questionId;
private String name;
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "category")
private Category category;
and
#Entity
#Table(name = "category")
public class Category {
#Id
#GeneratedValue
private Long categoryId;
private String name;
I have some list of categories and I would like to add new Question with selected Category. So in my QuestionController I have add method:
#RequestMapping(value = "/add", method = RequestMethod.GET)
public ModelAndView add() {
ModelAndView mav = new ModelAndView("question/add");
mav.addObject("question", new Question());
mav.addObject("categoryList", categoryService.getAll());
return mav;
}
and form:
<form:form modelAttribute="question" method="POST" >
Name: <form:input path="name" value="${ques.name}" />
Category: <form:select path="category" items="${categoryList}" />
<input type="submit" value="Add" />
</form:form>
Everything looks good for now (I can fill question name and select category). But I don't know how add POST method should work
#RequestMapping(value = "/add", method = RequestMethod.POST)
public String added(#ModelAttribute Question question, BindingResult bindingResult) {
}
When I try to use above method I have error: Failed to convert property value of type 'java.lang.String' to required type model.Category
I've tried to look for similar problem but I coudln't find anything.. So if someone can help/advice or show link to similar issue I would be grateful!
Cheers!
You need to provide code for Spring that tells it how to convert the string value from the web page back into a Category object. This is done by either:
Adding a PropertyEditor to the DataBinder.
Creating a Converter.
It is a bad practice using hibernate objects to map the form items. There are two solutions
Add another property private transient String categoryString; to the 'Question' class. and map the UI category to this <form:select path="categoryString" items="${categoryList}" />
That way you can avoid the error.
Do not use the hibernate mapping classes for mapping the form items, use POJOs for doing this. and later somewhere in your application map this simple pojo elements onto the hibernate entity.
try changing this line:
<form:select path="category" items="${categoryList}" />
to:
<form:select path="category.categoryId" items="${categoryList}" itemLabel="name" itemValue="categoryId"/>
Then in the added method (post method), retrieve the Category object back from hibernate and set back on question object before saving:
Category selectedCategory = yourHibernateService.getCategoryById(question.getCategory().getCategoryId());
question.setCategory(selectedCategory);

Categories