对于一个简单的客户管理应用程序,我在添加出生日期时遇到了问题!
这是我的html:
<label for="dob" class="firstThreeInputs">Date of Birth: </label>
<input type="date" [(ngModel)]="customer.dateOfBirth" class="" id="dateOfBirthInput" name="dateOfBirth" placeholder="Date of Birth">
当我添加新客户或编辑现有客户时,我会收到以下错误:
Failed executing PUT /customers/6: org.jboss.resteasy.spi.ReaderException: com.fasterxml.jackson.databind.exc.InvalidDefinitionException: Cannot construct instance of `java.time.LocalDate` (no Creators, like default construct, exist): no String-argument constructor/factory method to deserialize from String value ('2018-12-12')
看起来这是一个常见的问题,Jackson有一个解决方案,但我不知道如何在我的应用程序中实现它。
以下是我的客户类别:
import java.time.LocalDate;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.NamedQuery;
import javax.persistence.Table;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
//Data and Integration
@Entity
@Table(name ="basic_info")
@NamedQuery(name="Customers.selectAll", query="SELECT n From Customers n")
public class Customers {
@Id @GeneratedValue(strategy=GenerationType.IDENTITY)
private Long id;
@Column(length=100, nullable=false)
private String first_name;
@Column(length=100, nullable=false)
private String last_name;
@Column(length=100, nullable=false)
private String country_code;
@Column(length=100, nullable=false)
private String gender;
@Column(nullable=false)
private LocalDate dateOfBirth;
@Column(nullable=false)
private boolean isActive;
public Customers() {}
public Customers(Long id, String first_name, String last_name, LocalDate dateOfBirth) {
this.id = id;
this.first_name = first_name;
this.last_name = last_name;
this.dateOfBirth = dateOfBirth;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getFirstName() {
return first_name;
}
public void setFirstName(String first_name) {
this.first_name = first_name;
}
public String getLastName() {
return last_name;
}
public void setLastName(String last_name) {
this.last_name = last_name;
}
public LocalDate getDateOfBirth() {
return dateOfBirth;
}
public void setDateOfBirth(LocalDate dateOfBirth) {
this.dateOfBirth = dateOfBirth;
}
public String getCountryCode() {
return country_code;
}
public void setCountryCode(String country_code) {
this.country_code = country_code;
}
public String getGender() {
return gender;
}
public void setGender(String gender) {
this.gender = gender;
}
public boolean getActiveStatus() {
return isActive;
}
public void setActiveStatus(boolean isActive) {
this.isActive = isActive;
}
@Override
public String toString() {
return "Cusomters [id=" + id + ", First Name =" + first_name + ", Last Name=" + last_name + " DateOfBirth="+ dateOfBirth +" Gender= " + gender + "CountryCode=" + country_code + "]";
}
}
我如何添加Jackson代码,以便在PUT/POST时将JSON转换为Java,而在GET期间则相反?如何使用ObjectMapper和JavaTimeModule?
下面是我的客户资源类:
package at.technikumwien.webf;
import java.net.URI;
import java.util.List;
import java.util.logging.Logger;
import javax.inject.Inject;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.transaction.Transactional;
import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriInfo;
import javax.ws.rs.core.Response.Status;
@Path("/customers")
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
public class CustomersResource {
private static final Logger LOGGER = Logger.getLogger(CustomersResource.class.getName());
@PersistenceContext
private EntityManager em;
@Inject
private CustomersService customersService;
@Context
private UriInfo uriInfo;
@POST
@Transactional
public Response create(Customers customer) {
LOGGER.info("create >> customer=" + customer);
em.persist(customer);
URI uri = uriInfo.getAbsolutePathBuilder().path(customer.getId().toString()).build();
return Response.created(uri).build();
}
@PUT
@Path("/{id}")
@Transactional
public void update(@PathParam("id") long id, Customers customerUpdate) {
LOGGER.info("update >> id=" + id + ", customer=" + customerUpdate);
Customers customerOld = em.find(Customers.class, id);
if ( customerOld != null) {
customerOld.setFirstName(customerUpdate.getFirstName());
customerOld.setLastName(customerUpdate.getLastName());
customerOld.setDateOfBirth(customerUpdate.getDateOfBirth());
customerOld.setGender(customerUpdate.getGender());
customerOld.setCountryCode(customerUpdate.getCountryCode());
customerOld.setActiveStatus(customerUpdate.getActiveStatus());
}
else {
throw new WebApplicationException(Status.NOT_FOUND);
}
}
@DELETE
@Path("/{id}")
@Transactional
public void delete(@PathParam("id") long id) {
LOGGER.info("delete >> id=" + id);
Customers customer = em.find(Customers.class, id);
if (customer != null) {
em.remove(customer);
}
else {
throw new WebApplicationException(Status.NOT_FOUND);
}
}
@GET
@Path("/{id}")
public Customers retrieve(@PathParam("id") long id) {
LOGGER.info("retrieve id=" + id);
return em.find(Customers.class, id);
}
@GET
@Path("/")
public List<Customers> retrieveAll() {
LOGGER.info("retrieveAll");
return customersService.getAllCustomers();
}
}
正如您的错误所解释的,java.time类(如LocalDate
(没有公共构造函数。没有new LocalDate
。相反,这些类使用工厂方法,如这些命名约定所示。
LocalDate today = LocalDate.now() ; // Tip: Better to pass a `ZoneId`.
LocalDate tomorrow = today.plusDays( 1 ) ; // Immutable objects. So a new fresh `LocalDate` is instantiated based on values copied from original object.
LocalDate someDay = LocalDate.parse( "2020-01-23" ) ;
您的代码显然需要一个无arg构造函数。当然没有找到。
使用Jackson
处理LocalDate
的主题已经在Stack Overflow上进行了多次讨论。
我发现了一个很棒的博客,它解释了这一点:
https://kodejava.org/how-to-format-localdate-object-using-jackson/