1

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:

Overview 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">&times;</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";
}
  • You can refer this answer to change your toDate function to return a String with your pre-defined `"yyyy-MM-dd hh:mm:ss"` format: https://stackoverflow.com/questions/43322580/convert-date-to-string-in-format-dd-mmm-yyyy – Jun Bach Mar 20 '18 at 10:08
  • So you pass date from Javascript in another format or change parsing in Java – Justinas Jakavonis Mar 27 '18 at 06:18

0 Answers0