web-dev-qa-db-de.com

Spring REST, JSON "Verwalteter/rückseitiger Verweis 'defaultReference' kann nicht verarbeitet werden" "415 Nicht unterstützter Medientyp

Ich versuche, POST an http: // localhost: 9095/translators von einem AngularJS-Frontend mit Spring Boot/Spring RestController-Backend zu erstellen.

Ich kann ein GET machen und die Antwort ist wie folgt:

[{"userId":1,"firstName":"John","lastName":"Doe","emailId":"[email protected]","languages":[{"languageId":1,"languageCode":"gb","source":true}],"translations":[{"translationId":3,"sourceId":1,"sourceText":"Hello","targetId":null,"targetText":null,"translationStatus":"DUE"}],"userType":"TRANSLATOR"}

Wenn ich den folgenden Json poste, erhalte ich die error Antwort

POST data:

{
                    firstName: "zen",
                    lastName: "cv",
                    emailId: "email",
                    userType: "TRANSLATOR",
                    languages : [{languageId:1,languageCode:"gb",source:true}]
}

Error:

{
timestamp: 1422389312497
status: 415
error: "Unsupported Media Type"
exception: "org.springframework.web.HttpMediaTypeNotSupportedException"
message: "Content type 'application/json' not supported"
path: "/translators"
}

Ich habe sichergestellt, dass mein Controller über eine korrekte Mediatyp-Anmerkung verfügt.

@RestController
@RequestMapping("/translators")
public class TranslatorController {
    @Autowired
    private UserRepository repository;

    @RequestMapping(method = RequestMethod.GET)
    public List findUsers() {
        return repository.findAll();
    }

    @RequestMapping(value = "/{userId}", method = RequestMethod.GET)
    public User findUser(@PathVariable Long userId) {
        return repository.findOne(userId);
    }

    @RequestMapping(method = RequestMethod.POST, consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE)
    public User addTranslator(@RequestBody User user) {
        //translation.setTranslationId(null);
        return repository.saveAndFlush(user);
    }

    @RequestMapping(value = "/{translatorId}", method = RequestMethod.PUT)
    public User updateTranslation(@RequestBody User updatedUser, @PathVariable Long userId) {
        //updatedTranslation.setTranslationId(translationId);
        return repository.saveAndFlush(updatedUser);
    }

    @RequestMapping(value = "/{translatorId}", method = RequestMethod.DELETE)
    public void deleteTranslation(@PathVariable Long translationId) {
        repository.delete(translationId);
    }
}

Nach einiger Recherche und durch die Protokollausgabe erkenne ich, dass dies eine irreführende Fehlermeldung ist und das Problem tatsächlich beim Serialisieren/Deserialisieren von Json auftritt

In Protokolldatei finde ich

2015-01-27 21: 08: 32.488 WARN 15152 --- [nio-9095-exec-1] .CjMappingJackson2HttpMessageConverter: Fehler bei der Bewertung der Deserialisierung Für Typ [einfacher Typ, Klasse Benutzer ]: Java.lang.IllegalArgumentException: Kann nicht mit verwalteter/hinterer Referenz 'defaultReference' umgehen: Rückreferenztyp (Java.util.List) nicht mit Kompatibel mit verwaltetem Typ ( Nutzer)

Hier ist meine Klasse Benutzer- und Klassenübersetzung (Getter, Setter, Konstruktor etc. der Kürze halber weggelassen)

@Entity
@Table(name = "users")
public class User {

    @Id
    @GeneratedValue(strategy= GenerationType.AUTO)
    @Column(name = "user_id")
    private long userId;

    @Column(name = "first_name")
    private String firstName;

    @Column(name = "last_name")
    private String lastName;

    @Column(name = "email_id")
    private String emailId;

    @ManyToMany
    @JoinTable(name = "languages_users", joinColumns = { @JoinColumn(name = "user_id")},
            inverseJoinColumns = {@JoinColumn(name = "lang_id")})
    @JsonManagedReference
    private List<Language> languages = new ArrayList<Language>();

    @OneToMany(mappedBy = "translator", fetch = FetchType.EAGER)
    @JsonManagedReference
    private List<Translation> translations;

    @Enumerated(EnumType.STRING)
    private UserType userType;
}

@Entity
@Table(name = "translations")
public class Translation {

    @Id
    @GeneratedValue(strategy= GenerationType.IDENTITY)
    @Column(name = "translation_id")
    private Long translationId;

    @Column(name = "source_lang_id")
    private Long sourceId;

    @Column(name = "source_text")
    private String sourceText;

    @Column(name = "target_lang_id")
    private Long targetId;

    @Column(name = "target_text")
    private String targetText;

    @Enumerated(EnumType.STRING)
    @Column(name = "status")
    private TranslationStatus translationStatus;

    @ManyToOne
    @JoinColumn(name = "translator_id")
    @JsonBackReference
    private User translator;
}

Meine Frage ist folgende: Wie kann ich JsonManagedReference und JsonBackReference für die obigen Entitäten richtig einstellen? Ich habe das doc gelesen. und ich kann aufgrund der Fehlermeldung nicht herausfinden, was hier falsch ist

8
senseiwu

Ich habe es gelöst, indem ich JsonManagedReference und JsonBackReference loswurde und durch JsonIdentityInfo ersetze

6
senseiwu

Für diejenigen, die fragen, , Wäre ein alternativer Ansatz die Verwendung von JsonIdentityInfo von accelerxml und das Annotieren Ihrer Klasse mit:

import com.fasterxml.jackson.annotation.JsonIdentityInfo;
import com.fasterxml.jackson.annotation.ObjectIdGenerators;
@JsonIdentityInfo(generator=ObjectIdGenerators.PropertyGenerator.class, property="id")
public class Account implements Java.io.Serializable {
....
private Long id;
}

* Nicht genug Repräsentant zum Kommentieren.

9
Simon Lippens

Wie @Sharppoint in Kommentaren sagte, löste ich die Mine, indem ich @JsonManagedReference entfernte, aber @JsonBackReference behalten.

8

Sie benötigen @ResponseBody-Annotation wie folgt:

@RequestMapping(method = RequestMethod.POST, consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE)
    @ResponseBody public User addTranslator(@RequestBody User user) {
        //translation.setTranslationId(null);
        return repository.saveAndFlush(user);
    }
4
sndyuk

Kann dieses Problem lösen, indem Sie JsonManagedReference in der Basisklasse entfernen. @JsonBackReference erledigt die Arbeit, um die unendliche Wiederholung zu beenden, während die Daten vom Controller abgerufen/gesendet werden.

Ich gehe davon aus, dass Ihre Sprachklasse mehrere @JsonBackReference drin. Wenn Sie also die Benutzerdaten mit zwei darin enthaltenen Klassen senden, kann der Spring das Objekt nicht deserialisieren und dementsprechend zuordnen.

Sie können dieses Problem lösen, indem Sie einfach eines der @JsonBackReference aus einem der Übersetzungs/Sprachkurse und Ersetzen durch @JsonIgnore/@JsonIdentityInfo.

Auf diese Weise führen Sie buchstäblich das gleiche Mapping durch, schließen jedoch die mehrfachen @JsonBackReference an die Basisklasse, auf die eindeutig als Fehler hingewiesen wird, der zu 415 Unsupported media type exception.

0
sai kiran

Ich hatte den gleichen Fehler und löste das Entfernen aller Anmerkungen @JsonBackReference und @JsonManagedReference. Dann füge ich @JsonIdentityInfo in allen Klassen mit Beziehungen Ein. Überprüfen Sie die Dokumentation

0
Lupita Llamas