2016-06-02 35 views
0

nicht instanziieren Ich habe Java8 LocalDateTime in meinen Jax-RS-REST-APIs. Meine Webanwendung wird in wildfly10 bereitgestellt. Wenn ich einen POST-Aufruf (der LocalDateTime als Parameter enthält) mache, erhalte ich folgende Ausnahme;com.fasterxml.jackson.databind.JsonMappingException: Kann den Wert vom Typ [einfacher Typ, Klasse java.time.LocalDateTime] von String

Caused by: com.fasterxml.jackson.databind.JsonMappingException: Can not instantiate value of type [simple type, class java.time.LocalDateTime] from String value ('2016-06-02T00:08:25.605Z'); no single-String constructor/factory method 
at [Source: [email protected]; line: 2, column: 3] (through reference chain: com.leightonobrien.core.model.base.Company["created"]) 
    at com.fasterxml.jackson.databind.JsonMappingException.from(JsonMappingException.java:148) 
    at com.fasterxml.jackson.databind.DeserializationContext.mappingException(DeserializationContext.java:843) 
    at com.fasterxml.jackson.databind.deser.ValueInstantiator._createFromStringFallbacks(ValueInstantiator.java:277) 
    at com.fasterxml.jackson.databind.deser.std.StdValueInstantiator.createFromString(StdValueInstantiator.java:284) 
    at com.fasterxml.jackson.databind.deser.BeanDeserializerBase.deserializeFromString(BeanDeserializerBase.java:1150) 
    at com.fasterxml.jackson.databind.deser.BeanDeserializer._deserializeOther(BeanDeserializer.java:153) 
    at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:144) 
    at com.fasterxml.jackson.databind.deser.SettableBeanProperty.deserialize(SettableBeanProperty.java:523) 
    at com.fasterxml.jackson.databind.deser.impl.FieldProperty.deserializeAndSet(FieldProperty.java:101) 
    at com.fasterxml.jackson.databind.deser.impl.BeanPropertyMap.findDeserializeAndSet(BeanPropertyMap.java:285) 
    at com.fasterxml.jackson.databind.deser.BeanDeserializer.vanillaDeserialize(BeanDeserializer.java:248) 

Basierend auf folgenden Anleitungen;

Wildfly throws "Unable to find a constructor that takes a String param or a valueOf() or fromString() method for javax.ws.rs.QueryParam" error

und

jaxrs could not find my custom (de)serializers for joda.money type

und

https://github.com/FasterXML/jackson-datatype-jsr310

Ich habe mein Provider und eingetragen in den Anwendungspfad geschrieben;

package com.test; 

import java.lang.annotation.Annotation; 
import java.lang.reflect.Type; 
import java.time.LocalDateTime; 
import java.time.format.DateTimeFormatter; 

import javax.ws.rs.ext.ParamConverter; 
import javax.ws.rs.ext.ParamConverterProvider; 
import javax.ws.rs.ext.Provider; 

import com.fasterxml.jackson.databind.ObjectMapper; 
import com.fasterxml.jackson.databind.SerializationFeature; 
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; 
import com.fasterxml.jackson.jaxrs.json.JacksonJsonProvider; 

@Provider 
public class LocalDateTimeConverterProvider extends JacksonJsonProvider implements ParamConverterProvider { 

    private final LocalDateTimeConverter converter = new LocalDateTimeConverter(); 

    @Override 
    public <T> ParamConverter<T> getConverter(Class<T> rawType, Type genericType, Annotation[] annotations) { 
     if (!rawType.equals(LocalDateTime.class)) 
      return null; 
     return (ParamConverter<T>) converter; 
    } 

    public class LocalDateTimeConverter implements ParamConverter<LocalDateTime> { 

     @Override 
     public LocalDateTime fromString(String value) { 
      DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm"); 
      LocalDateTime dateTime = LocalDateTime.parse(value, formatter); 
      return dateTime; 
     } 

     @Override 
     public String toString(LocalDateTime value) { 
      DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm"); 
      String formattedDateTime = value.format(formatter); 
      return formattedDateTime; 
     } 

    } 

    public LocalDateTimeConverterProvider() { 

     ObjectMapper mapper = new ObjectMapper(); 

     mapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS); 

     mapper.registerModule(new JavaTimeModule()); 

     setMapper(mapper); 
    } 

} 



import javax.ws.rs.ApplicationPath; 

@ApplicationPath("/rest") 
public class RestApplication extends Application { 
@Override 
    public Set<Class<?>> getClasses() { 
     HashSet<Class<?>> set = new HashSet<Class<?>>(); 
     set.add(com.test.JsonMoneyProvider.class); 
     set.add(com.test.DurtaionConverterProvider.class); 
     set.add(com.test.LocalDateTimeConverterProvider.class); 
     set.add(com.test.MoneyConverterProvider.class); 
... 

Ich mache POST Anruf wie;

curl -X POST --header 'Content-Type: application/json' -d '{ 
    "created": "2016-06-02T00:08:25.605Z", 
    "updated": "2016-06-02T00:08:25.605Z", 
    "id": 0, 
    "code": "string", 
    "name": "string", 
    "abn": "string", 
    "addresses": [ 
    { 
     "id": 0, 
     "address1": "string", 
     "address2": "string", 
     "city": "string", 
     "state": "string", 
     "postcode": "string", 
     "country": "string", 
     "gps": { 
     "latitude": { 
      "latitude": 0, 
      "value": 0 
     }, 
     "longitude": { 
      "longitude": 0, 
      "value": 0 
}' 'http://localhost:8080/test2dbwar/rest/Companys' 

Wie kann ich das obige Problem lösen? Jetzt bin ich ahnungslos .. Ich habe versucht, alle Sachen (versuchen zu vermeiden, Wildfly jax-rs komplexe Unterstützung Problem, jackson Serialisierung Problem) und sortiere das Problem.

Irgendwelche Hilfe?

Antwort

1

Die erste Frage, mit der Sie verknüpft haben, betrifft die Konvertierung von @XxxParam Annotationen. Dies ist, was die ParamConverterProvider ist. Dies ist ein vollständig anderer (De) serailization Prozess von Entität Körper (de) Serialisierung.

Für die Entity (de) -Serialisierung werden MessageBodyReader/MessageBodyWriter s verwendet. Jackson bietet eine solche Implementierung in seiner JacksonJsonProvider/JacksonJaxbJsonProvider, die Sie derzeit verwenden, ob Sie es wissen oder nicht. Also muss die Konfiguration für die LocalDataTime irgendwie mit diesem Provider konfiguriert werden.

Die einzige Möglichkeit, Jackson-Unterstützung für die LocalDateTime Serialisierung zu konfigurieren, ist durch ObjectMapper. Sie können eine benutzerdefinierte Json(De)Serializer, wie erwähnt in this post (Option two), oder Sie können die JSR310Module verwenden (die bereits benutzerdefinierte Json(De)Serializer für LocalDateTime), in this post erwähnt.

So konfigurieren Sie tatsächlich die JacksonJsonProvider/JacksonJaxbJsonProvider Ihre Konfiguration verwendet ObjectMapper Sie eine ContextResolver verwenden können, wie in den beiden vorhergehenden Links erwähnt, oder Sie können die JacksonJsonProvider mit dem ObjectMapper, bauen und registrieren, dass Anbieter

ObjectMapper mapper = new ObjectMapper(); 
mapper..configurModuleOrSerializer 
JacksonJsonProvider provider = new JacksonJsonProvider(mapper); 
registerProvier(provider) 

Persönlich würde ich einfach mit der ContextResolver gehen, wie in den Links erwähnt. Der Unterschied ist, dass mit dem obigen Code die ObjectMapper dem Provider explizit zur Verfügung gestellt wird, während mit der ContextResolver, während der Laufzeit der Provider die JAX-RS-Registrierung für eine ContextResolver des Typs ObjectMapper suchen und dann erhalten Sie auf diese Weise.

+0

Sorry, Ich bin wirklich neu in den Ruhezustand. Danke für die klare Erklärung. Es hat das Problem gelöst. – Ratha

0

In meinem Fall, das Hinzufügen der folgenden Arbeiten für mich.

<dependency> 
    <groupId>com.fasterxml.jackson.datatype</groupId> 
    <artifactId>jackson-datatype-jsr310</artifactId> 
    <version>2.8.9</version 
</dependency> 

und konfigurieren Sie den ObjectMapper wie folgt aus:

ObjectMapper mapper = new ObjectMapper().registerModule(new JavaTimeModule());