How to send thymeleaf value to spring controller - spring

I am new with Spring and Thymeleaf. I am building a simple app to rate films and series. I have a html table with some information about serie including current rating. To display a current rate I need to send a serie id to my spring controller, but don't know how to do that. I was trying with th:with="serie_Id=${tempSerie.id}" but it doesn't work as I wish. The theId variable is always null.
Here is my controller:
#GetMapping("/list")
public String listSeries(#Param("serie_Id") Integer theId, Model theModel, #Param("keyword") String keyword){
String username;
Object principal = SecurityContextHolder.getContext().getAuthentication().getPrincipal();
if(principal instanceof UserDetails){
username = ((UserDetails)principal).getUsername();
}
else {
username = principal.toString();
}
System.out.println(theId);
User theUser = userService.findByUsername(username);
Serie theSerie = serieService.findById(theId);
int theRating;
try{
theRating = serieRatingService.findByUserAndSerie(theUser, theSerie).getSerieRating();
}
catch (NullPointerException e){
theRating = 0;
}
List<Serie> theSeries = serieService.findAll(keyword);
theModel.addAttribute("serie_Id", theId);
theModel.addAttribute("series", theSeries);
theModel.addAttribute("ratings", theSeries);
theModel.addAttribute("keyword", keyword);
theModel.addAttribute("theRating", theRating);
return "series/list-series";
}
Here is snippet of my view:
<table class="table table-bordered table-striped">
<thead class="thead-dark">
<tr>
<th>Title</th>
<th>Release Year</th>
<th>Current Rate</th>
<th>Action</th>
</tr>
</thead>
<tbody>
<tr th:each="tempSerie : ${series}">
<td th:text="${tempSerie.title}" />
<td th:text="${tempSerie.release_year}" />
<td>
<p><svg width="1em" height="1em" viewBox="0 0 16 16" class="bi bi-star-fill" fill="currentColor" xmlns="http://www.w3.org/2000/svg">
<path d="M3.612 15.443c-.386.198-.824-.149-.746-.592l.83-4.73L.173 6.765c-.329-.314-.158-.888.283-.95l4.898-.696L7.538.792c.197-.39.73-.39.927 0l2.184 4.327 4.898.696c.441.062.612.636.283.95l-3.523 3.356.83 4.73c.078.443-.36.79-.746.592L8 13.187l-4.389 2.256z"/>
</svg><span th:with="serie_Id=${tempSerie.id}" th:text="${theRating}"></span></p>
</td>
<td>
<div sec:authorize="hasRole('ROLE_ADMIN')">
<a th:href="#{/series/showFormForUpdate(serieId=${tempSerie.id})}"
class="btn btn-info btn-sm">
Update
</a>
<a th:href="#{/series/delete(serieId=${tempSerie.id})}"
class="btn btn-danger btn-sm"
onclick="if (!(confirm('Are you sure?'))) return false">
Delete
</a>
</div>
<div sec:authorize="hasRole('ROLE_USER')">
<a th:href="#{/serieRatings/showFormForSerieRate(serieId=${tempSerie.id})}"
class="btn btn-warning">
Rate
</a>
</div>
</td>
</tr>
</tbody>
</table>
I want my table to be like this. The serie id is just hard-coded.
https://i.stack.imgur.com/3w7yQ.png

Try to change your solution for this one. In general, read about Path Variables.
<a th:href="#{/serieRatings/showFormForSerieRate/${tempSerie.id}}"
class="btn btn-warning">
Rate
</a>
And your controller
#GetMapping("/list/{id}")
public String listSeries(#PathVariable Integer id)
{
serieService.findById(id);
...
}
You can of course do something similar with keyword.
Let me know if it makes the trick.

I added user and my services to model and used them in the view. Maybe this approach is not the best but it works a desired. My controller:
#GetMapping("/list")
public String listSeries(Model theModel, #Param("keyword") String keyword){
String username;
Object principal = SecurityContextHolder.getContext().getAuthentication().getPrincipal();
if(principal instanceof UserDetails){
username = ((UserDetails)principal).getUsername();
}
else {
username = principal.toString();
}
User theUser = userService.findByUsername(username);
List<Serie> theSeries = serieService.findAll(keyword);
theModel.addAttribute("series", theSeries);
theModel.addAttribute("keyword", keyword);
theModel.addAttribute("theService", serieService);
theModel.addAttribute("theRatingService", serieRatingService);
theModel.addAttribute("user", theUser);
return "series/list-series";
}
Snippet of my view:
<td th:text="${tempSerie.title}" />
<td th:text="${tempSerie.release_year}" />
<td>
<p><svg width="1em" height="1em" viewBox="0 0 16 16" class="bi bi-star-fill" fill="currentColor" xmlns="http://www.w3.org/2000/svg">
<path d="M3.612 15.443c-.386.198-.824-.149-.746-.592l.83-4.73L.173 6.765c-.329-.314-.158-.888.283-.95l4.898-.696L7.538.792c.197-.39.73-.39.927 0l2.184 4.327 4.898.696c.441.062.612.636.283.95l-3.523 3.356.83 4.73c.078.443-.36.79-.746.592L8 13.187l-4.389 2.256z"/>
</svg><span th:text="${theRatingService.findByUserAndSerie(user, theService.findById(tempSerie.id))?.getSerieRating()}"></span></p>
</td>

Related

DropdownlistFor in a loop, null model on submit

I am having an issue with the values selected in multiple dropdownlistfor(s) being available in the controller when the form is submitted. The model is always blank. I know there are issues with mvc having dropdowns in loops but I thought I have solved for this. Let me know what you think.
View
#model DataDictionaryConversion.Models.FinalResults
#{ using (Html.BeginForm("SaveMapping", "Home", FormMethod.Post, null))
{
#Html.AntiForgeryToken()
<table class="table table-striped">
<thead>
<tr>
<th>Converted to Name</th>
<th>Your Project Name</th>
<th><input type="button"
onclick="checkAll()"/></th>
</tr>
</thead>
<tbody>
#{for (int x = 0; x < Model.DDObjects.Count(); x++)
{
var isSelection = false;
<tr>
<td class="filterable-cell">#Model.DDObjects[x].ObjectName</td>
<td class="filterable-cell">
#Html.DropDownList(Model.DDObjects[x].ObjectName, new
SelectList(Model.ProjectObjects, "ObjectName", "ObjectName"),
htmlAttributes: new { #id = "ddlObject", #class = "js-example-basic-single" })</td>
</td>
<td>
<input type="checkbox" id="NoValue-
#Model.DDObjects[x].ObjectName" name="NoValue-
#Model.DDObjects[x].ObjectName" onclick="byPassObject(this)" /> Object
Not
Used
</td>
</tr>
}
}
</tbody>
<tfoot>
<tr>
<td style="text-align:right; height:20px"><input
type="submit" class="btn btn-warning" value="Generate Conversion Mapping"
/></td>
</tr>
</tfoot>
</table>
}
}
Controller
[HttpPost]
public ActionResult SaveMapping([FromServices]ApplicationDbContext context, FinalResults model)
{
return View("Mapping");
}
Model
public class FinalResults
{
public IList<FinalObjectModel> ProjectObjects { get; set; }
public IList<Conversion_CSD_ObjectNameLearningModel> DDObjects {
get; set; }
FinalResults model is null
You're using Html.DropDownList. The first param there is a string, which should correspond with the name you're binding to. However, you're passing the value of Model.DDObjects[x].ObjectName, not literally something like "DDOjbects[0].ObjectName".
Instead, you should be using Html.DropDownListFor like so:
#Html.DropDownListFor(m => m.DDObjects[x].ObjectName, ...)
Then, the select list will be bound correctly.

BadRequest Error in ajax with Spring MVC

I am trying post a request to my controller and everytime when I hit submit button it gives an error of bad request.
I am not able to find out what is wrong with the code.
Home.jsp
<div id="setReminder">
<label class="generalReminder" style="text-decoration: none;">General
Reminder</label>
<table>
<tr>
<td>Date</td>
<td><input type="text" readonly="readonly"
id="birthdayDate"></td>
</tr>
<tr>
<td>Time</td>
<td><input type="text" readonly="readonly" id="callTime"
></td>
</tr>
<tr>
<td>Message</td>
<td><textarea id="reminderTag" rows="5"></textarea></td>
</tr>
</table>
</div>
<div id="reminderDot" style="margin-top: 24%; position: relative;">
<button class="submitReminder" onclick="saveReminderDetails();">Submit</button>
</div>
Home.js
function saveReminderDetails(){
var x="";
x=scheduleBirthdayReminder();
if(x){
$.ajax({
type:"POST",
url:"submitBirthdayRequest.do",
data : {
birthdayDate :$("#birthdayDate").val(),
birthdayTime : $("#callTime").val(),
birthdayReminder : $("#reminderTag").val()
},
success : function(data) {
alert('data is'+data);
$("#birthdayDate").val('');
$("#callTime").val('');
$("#reminderTag").val('');
}
});
}
}
Controller.java
#RequestMapping(value="submitBirthdayRequest.do",method=RequestMethod.POST)
public #ResponseBody String submitSchedulerDetails(#RequestParam("birthdayDate")String birthdayDate,#RequestParam("callTime")String birthdayTime,#RequestParam("reminderTag")String reminderTag,HttpServletRequest request ){
System.out.println("adding reminder details with birthdayDate "+birthdayDate+"and time"+birthdayTime);
String userIdentity=((UserDetails)request.getSession(false).getAttribute("loginDetails")).getName();
try{
boolean schedulerObj= schedulerService.addSchedulerBirthdayDetails(userIdentity,birthdayDate, birthdayTime,reminderTag);
}catch(Exception e){
e.printStackTrace();
}
return birthdayTime;
}
Error
http://localhost:8083/Testing/submitBirthdayRequest.do 400 (Bad Request)
the names of the parameters in the request don't match the expected. Try changing the
#RequestParam("birthdayTime") String birthdayTime
#RequestParam("birthdayReminder") String reminderTag
or change the param names on the client side

Passing image to JSP in Spring MVC java with mango

Hi I am reading image from MongoDB and trying to pass that to JSP page but it is not passing properly from my controller. i am thinking i am almost edge to the solution but not getting exactly where i am doing mistake. Please let me know if you find any mistake.
here insertMedia method reading image from file and storing into DB and then returning back that image.
i am passing userMediaSave as image value to JSP, you can get that at tag like
img src=${userMediaSave} alt="Profile images"
My Controller:
#RequestMapping(value = "/userMediaSave", method = RequestMethod.GET)
public ModelAndView mediaLoadSuccess(HttpServletRequest request,HttpServletResponse response,
#ModelAttribute("mediaBean") MediaBean mediaBean) throws IOException, ServletException {
ModelAndView model = null;
File filePart = mediaBean.getMediaImage();
if (filePart != null) {
InputStream inputStream = new FileInputStream(filePart);
GridFSDBFile imageForOutput = null;
try {
imageForOutput = loginDelegate.insertMedia(inputStream, request.getContentType(), filePart.getName());
mediaBean.setExistedMedia(imageForOutput);
OutputStream out= null;
if(imageForOutput!=null){
InputStream is = imageForOutput.getInputStream();
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
int nRead;
byte[] data = new byte[16384];
while ((nRead = is.read(data, 0, data.length)) != -1) {
buffer.write(data, 0, nRead);
}
byte[]imagenEnBytes = buffer.toByteArray();
buffer.flush();
response.setContentType("image/jpg" );
response.setContentLength(imagenEnBytes.length);
model = new ModelAndView("userMedia");
request.setAttribute("userMediaSave", imagenEnBytes);
return model;
} else {
System.out.println("inside uploadMedia page -ve");
}
} catch (SQLException e) {
e.printStackTrace();
} finally{
//out.close();
}
}
return model;
}
JSP is:
<body onload="checkMessage()">
<form:form id="mediaForm" method="get" action="userMediaSave" modelAttribute="mediaBean">
<table border="1" cellpadding="1" cellspacing="1"
style="width: 500px;" align="center">
<tbody>
<tr>
<td colspan="4" align="center">Name : Welcome to Media App</td>
</tr>
<tr>
<td rowspan="3">Profile Image</td>
<td>Upload Images</td>
<td><input type="file" name="mediaImage" /></td>
</tr>
<tr>
<td> </td>
<td><input name="upload" type="submit" value="Upload" /></td>
</tr>
</tbody>
</table>
<table border="1" cellpadding="1" cellspacing="1"
style="width: 500px;" align="center">
<tbody>
<tr>
<td>User has some existed Media Album</td>
</tr>
<tr>
<td>
<img src=${userMediaSave} alt="Profile images" style="width:100px;height:100px;">
</td>
</tr>
</tbody>
</table>
</form:form>
am i passing image from controller to JSP properly? if not please let me know which way i have to pass it.

Data not populating on page after processing post request

it shows data when get request is send properly but when i save data with post requset then again the page is rendered data is not coming on page
This is my controller code
#RequestMapping(value = "/incident", method = RequestMethod.GET)
public String add_incident(Model model,HttpSession session) {
try{
List<AddIncident> fetchincident = incService.fetchIncident();
String user_id = ""+session.getAttribute("session");
List<AddIncident> fetchuserincident = incService.fetchuserincident(user_id);
//group work
User user = new User();
model.addAttribute("user", user);
List<User> fetchListByUsername = userService.findListByUserName(user_id);
String department = fetchListByUsername.get(0).getDepartment();
List<AddIncident> fetchgroupincident = incService.fetchgroupincident(department);
System.out.println(fetchgroupincident.get(0).getAssignTo());
System.out.println(fetchgroupincident.get(0).getSeverity());
model.addAttribute("fetchincident", fetchincident);
model.addAttribute("fetchgroupincident", fetchgroupincident);
model.addAttribute("fetchuserincident", fetchuserincident);
}catch(Exception e){
e.printStackTrace(); }
AddIncident incident = new AddIncident();
model.addAttribute("incident", incident);
return "incident";
}
#RequestMapping(value = "/incident", method = RequestMethod.POST)
public String add_incident(
#Valid #ModelAttribute("incident") AddIncident incident,
BindingResult result, Model model,HttpSession session) {
if (result.hasErrors()) {
return "incident";
} else {
User user=new User();
System.out.println(""+session.getAttribute("session"));
String user_id = ""+session.getAttribute("session");
System.out.println(user_id);
List<User> fetchListByUsername = userService.findListByUserName(user_id);
String department = fetchListByUsername.get(0).getDepartment();
System.out.println(department);
try{
List<User> fetchgroupuser = userService.findListByGroup(department);
ArrayList<String> email=new ArrayList<String>();
System.out.println(email);
for(User use:fetchgroupuser){
email.add(use.getEmail());
}
String[] to = new String[email.size()];
to = email.toArray(to);
System.out.println(to);
/*new String[]{"irasoftwares6#gmail.com","bluemagictest#gmail.com"};*/
String from = "Anurag.yv19#gmail.com";
String sub= "Incident Management System";
String msgBody="New Incident created";
incService.save(incident);
emailService.sendEmail(to , from, sub, msgBody);
}catch(ArrayIndexOutOfBoundsException e){e.printStackTrace();}
incident_logger.log(INCIDENT, incident.getRef_id()+" \n Assigned to :"+session.getAttribute("session"));
model.addAttribute("message", "Saved incident details");
return "incident";
}
}
my jsp code
<div class="table-responsive" id="inc-table" style="min-height: 280px;">
<form action="" method="get">
<div class="input-group">
<!-- USE TWITTER TYPEAHEAD JSON WITH API TO SEARCH -->
<input class="form-control" id="system-search" name="q" placeholder="Search for" required>
<span class="input-group-btn">
<button type="submit" class="btn btn-default"><i class="glyphicon glyphicon-search"></i></button>
</span>
</div>
</form>
<table class="table table-list-search table-bordered table-stripped table-hover">
<thead>
<tr>
<th>Ref. No.</th>
<th>Created</th>
<th>Severity</th>
<th>State</th>
<th>Assigned</th>
<th>Est</th>
<th>Description</th>
<th>Location</th>
<th>Config-item</th>
<th>Symptom Code</th>
<th>Closure Code</th>
<th>Submitted BY</th>
</tr>
</thead>
<tbody>
<c:forEach var="fetchuserincident" items="${fetchuserincident}">
<tr>
<td id="1" class="click" ><a href=""/>${fetchuserincident.ref_id}</td>
<td>${fetchuserincident.created}</td>
<td>${fetchuserincident.severity}</td>
<td>${fetchuserincident.state}</td>
<td>${fetchuserincident.assignTo}</td>
<td>${fetchuserincident.escalation}</td>
<td>${fetchuserincident.description}</td>
<td>${fetchuserincident.location}</td>
<td>${fetchuserincident.config_Item}</td>
<td>${fetchuserincident.symptom_code}</td>
<td>${fetchuserincident.closure_code}</td>
<td>${fetchuserincident.submittedby}</td>
<td> <button id="editbtn" class="fa fa-pencil">Edit</button></td>
</tr>
</c:forEach>
</tbody>
</table>
</div>
<hr>
<br>
My Group Work
Ref. No.
Created
Severity
State
Assigned
Est
Description
Location
Config-item
Symptom Code
Closure Code
Submitted BY
${fetchgroupincident.ref_id}
${fetchgroupincident.created}
${fetchgroupincident.severity}
${fetchgroupincident.state}
${fetchgroupincident.assignTo}
${fetchgroupincident.escalation}
${fetchgroupincident.description}
${fetchgroupincident.location}
${fetchgroupincident.config_Item}
${fetchgroupincident.symptom_code}
${fetchgroupincident.closure_code}
${fetchgroupincident.submittedby}
Edit

EditorTemplate + Model not being returned on POST

I can't seem to figure this out, it is driving me crazy!
Essentially, I have a list of rows I need to display with one drop down list per row.
I have a view model:
public class UserMembershipViewModel:BaseViewModel
{
public List<ProgramMembership> ProgramMembership { get; set; }
}
In my parent view I have, as you can see I am using an editor template which is located in "/Views/Shared/EditorTemplates/ProgramMembership.cshtml":
#using AcnCS.Model
#model AcnCS.Model.ViewModels.User.UserMembershipViewModel
#{
ViewBag.PageHeader = "Membership for " + Model.User.FullName;
ViewBag.PageTitle = "Membership for " + #Model.User.FullName;
ViewBag.HideNav = true;
}
#if (Model.ProgramMembership != null)
{
<div class="row-fluid">
<div class="span12">
<div id="permissions">
#using (Html.BeginForm())
{
<table class="table table-bordered">
<thead>
<tr>
<td>Program</td>
<td>Effective Membership?</td>
<td>Permission Type</td>
</tr>
</thead>
#Html.EditorFor(m => Model.ProgramMembership, "ProgramMembership")
</table>
<input type="submit" class="btn btn-primary" value="Save Changes"/>
}
</div>
</div>
</div>
}
My Editor template (ProgramMembership.cshtml) is:
#using AcnCS.Model
#model List<AcnCS.Model.ProgramMembership>
#foreach(ProgramMembership membership in Model)
{
<tr>
<td>#membership.ProgramName</td>
<td>
#if (membership.IsMember)
{
<span class="label label-success">#membership.IsMember</span>
}
else
{
#membership.IsMember
}
</td>
<td>#Html.DropDownListFor(x => membership.PermissionType, membership.PermissionTypes)</td>
</tr>
}
Everything is being displayed properly, but when I submit, my model object is null, even the ProgramMembership property in the model is null:
[HttpPost]
public ActionResult Membership(UserMembershipViewModel model)
{
// model IS NULL!!
return View(model);
}
Any help would be greatly appreciated!
I would pluralize the Property name since it is a collection, for better readability
public class UserMembershipViewModel:BaseViewModel
{
public List<ProgramMembership> ProgramMemberships { get; set; }
}
and you dont need a Loop inside your EditorTemplate file
#model AcnCS.Model.ProgramMembership
<tr>
<td>#membership.ProgramName</td>
<td>
#if (membership.IsMember)
{
<span class="label label-success">#membership.IsMember</span>
}
else
{
#membership.IsMember
}
</td>
<td>#Html.DropDownListFor(x => membership.PermissionType, membership.PermissionTypes)</td>
</tr>
In your main view,call your EditorTemplate like this
#Html.EditorFor(m=>m.ProgramMemberships)

Resources