First of all i'm working on a spring boot application. In my page where I try to create an invoice, I fill in a dueDate. All the information inside of this window:
is passed trough an ajax call to the controller via an invoiceForm. ( see code at the end )
but now I get this error:
"{"timestamp":"2018-03-20T09:31:24.479+0000","status":400,"error":"Bad Request","exception":"org.springframework.http.converter.HttpMessageNotReadableException","message":"Could not read document: Can not deserialize value of type java.util.Date from String \"2018-03-19T23:00:00.000Z\": expected format \"yyyy-MM-dd hh:mm:ss\"\n at [Source: java.io.PushbackInputStream@5f8a9170; line: 1, column: 45] (through reference chain: com.pegusapps.dashboard.Invoices.web.InvoiceForm[\"dueDate\"]); nested exception is com.fasterxml.jackson.databind.exc.InvalidFormatException: Can not deserialize value of type java.util.Date from String \"2018-03-19T23:00:00.000Z\": expected format \"yyyy-MM-dd hh:mm:ss\"\n at [Source: java.io.PushbackInputStream@5f8a9170; line: 1, column: 45] (through reference chain: com.pegusapps.dashboard.Invoices.web.InvoiceForm[\"dueDate\"])","path":"/finance/invoice/saveInvoice"}"
I expect it has to do with the date format not being in the correct form. How do I create the correct date from the extracted date string.
CODE:
MODAL
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal">×</button>
<h4 class="modal-title">New invoice</h4>
</div>
<div class="modal-body" style="display: inline-block;" >
<div style="width: 48%; float: left; margin: 5px">
<select class="selectpicker" style="width:100%" required id="chooseContract">
<option value="" selected disabled hidden>Choose a contract</option>
<option th:each="project : ${projects}" th:data-status="${project.status}" th:text="${project.name}"></option>
</select></div>
<div style="float: right;width: 48%">
<input class="form-control" style="width: 100%;margin: 5px;" id="datetimepicker" placeholder="DueDate" name="dueDate" required/>
<textarea class="form-control" id="remarks" rows="9" style="width: 100%; resize: none;margin: 5px"placeholder="Remarks" name="remarks"></textarea>
</div>
<input class="form-control" id="amount" type="number" style="float: left;clear: left;margin: 5px;width: 48%"placeholder="Amount" name="amount" required/>
<input class="form-control" id="discount" type="number" min="0" step="0.5" style="float: left;resize: none;clear:left;margin: 5px;width: 48%"placeholder="Discount" name="discount" required/>
<textarea class="form-control" id="description" rows="4"style="float: left;resize: none;clear:left;width: 48%;margin: 5px" placeholder="Description" name="description"></textarea>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
<button class="btn" style="background: #a81616; color: white;" type="submit" onclick="saveInvoice()">Save invoice</button>
</div>
</div>
Ajax call + transform date
function toDate(dateStr) {
var parts = dateStr.split("/");
return new Date(parts[2], parts[1] - 1, parts[0]);
}
function saveInvoice(){
console.log("succesvol saved invoice");
console.log(toDate($("#datetimepicker").val()));
var data = {}
data["contract"] = $("#chooseContract").val();
data["dueDate"] = toDate($("#datetimepicker").val());
data["remarks"] = $("#remarks").val();
data["amount"] = $("#amount").val();
data["discount"] = $("#discount").val();
data["description"] = $("#description").val();
$.ajax({
type: "POST",
contentType: "application/json",
url: window.location.href + "/saveInvoice",
data: JSON.stringify(data),
dataType: 'json',
timeout: 600000,
success: function (data) {
refresh();
},
error: function (e) {
console.log(e);
}
});
};
InvoiceForm
package com.pegusapps.dashboard.Invoices.web;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.pegusapps.dashboard.Invoices.Invoice;
import com.pegusapps.dashboard.Invoices.InvoiceId;
import com.pegusapps.dashboard.Invoices.InvoiceService;
import com.pegusapps.dashboard.Invoices.InvoiceType;
import com.pegusapps.dashboard.customer.web.ValidCustomerForm;
import com.pegusapps.dashboard.project.AbstractProject;
import lombok.*;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
import java.time.LocalDateTime;
import java.util.Date;
import java.util.UUID;
@Getter
@Setter
@AllArgsConstructor
@NoArgsConstructor
@ValidInvoiceForm
public class InvoiceForm {
private UUID id;
@NonNull
@Temporal(TemporalType.DATE)
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd hh:mm:ss")
private Date invoiceDate;
@NonNull
@Temporal(TemporalType.DATE)
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd hh:mm:ss")
private Date dueDate;
@NonNull
private double amount;
private String description;
private double discount;
@NonNull
private InvoiceType type;
private String remarks;
@NonNull
private Boolean sent;
@NonNull
private Boolean paid;
private AbstractProject project;
public Invoice asInvoice(InvoiceId id, InvoiceService invoiceService){
return new Invoice(id, new Date(), getDueDate(), getAmount(), getDescription(), getDiscount(), InvoiceType.NON_INVOICED_RANGE, getRemarks(),
getSent(), getPaid(), getProjectForm(invoiceService, id));
}
private AbstractProject getProjectForm(InvoiceService invoiceService, InvoiceId id){
if(project == null){
return invoiceService.getProject(id).orElse(null);
}else{
return project;
}
}
public static InvoiceForm create(Invoice invoice){
return new InvoiceForm(invoice.getId().getId(),invoice.getInvoiceDate(), invoice.getDueDate(), invoice.getAmount(), invoice.getDescription(), invoice.getDiscount(),
invoice.getType(), invoice.getRemarks(), invoice.getSent(), invoice.getPaid(),getProjectOrNull(invoice.getProject()));
}
private static AbstractProject getProjectOrNull(AbstractProject project){
if(project == null){
return null;
}else{
return project;
}
}
}
Controller method
@RequestMapping(value= "/saveInvoice", method = RequestMethod.POST)
public String saveCreatedInvoice(@Valid @RequestBody final InvoiceForm invoiceForm, BindingResult bindingResult, Model model) {
if (bindingResult.hasErrors()) {
model.addAttribute(INVOICE_ATTRIBUTE);
model.addAttribute(CREATE_ATTRIBUTE, true);
model.addAttribute(Invoice_ATTRIBUTE, service.getInvoices());
return INVOICE_EDIT_PATH;
}
service.save(invoiceForm.asInvoice(service.nextId(), service));
return "redirect:/finance/invoice";
}