web-dev-qa-db-fra.com

Spring REST, JSON "Impossible de gérer la référence par défaut" defaultReference "" 415 non prise en charge

J'essaie de POST to http: // localhost: 9095/translators à partir d'un serveur AngularJS à l'aide du backend Spring boot/Spring RestController.

Je peux faire un GET et la réponse est la suivante:

[{"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"}

Lorsque je poste le json ci-dessous, je reçois la réponse error

POST data:

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

Erreur:

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

Je me suis assuré que mon contrôleur possède l'annotation Mediatype correcte.

@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);
    }
}

Après quelques recherches et aussi en voyant la sortie du journal, je me rends compte qu'il s'agit d'un message d'erreur trompeur et que le problème se produit lors de la sérialisation/désérialisation de Json.

Dans le fichier de log, je trouve

2015-01-27 21: 08: 32.488 WARN 15152 --- [nio-9095-exec-1] .CjMappingJackson2HttpMessageConverter: Échec de l'évaluation de la désérialisation Pour le type [type simple, classe User ]: Java.lang.IllegalArgumentException: Impossible de gérer les références gérées/arrière 'DefaultReference': type de référence arrière (Java.util.List) non compatible avec le type géré ( Utilisateur)

Voici ma classe utilisateur et traduction de classe (getter, setter, constructeur, etc. omis pour plus de brièveté)

@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;
}

Ma question est la suivante: comment définir correctement JsonManagedReference et JsonBackReference pour les entités ci-dessus? J'ai lu le doc. et je ne peux pas comprendre ce qui ne va pas ici en fonction du message d'erreur

8
senseiwu

Je l'ai résolu en éliminant JsonManagedReference et JsonBackReference et en le remplaçant par JsonIdentityInfo.

6
senseiwu

Pour ceux qui demandent, Une autre approche serait d’utiliser JsonIdentityInfo, plus rapide, et d’annoter votre classe avec:

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;
}

* Je n'ai pas eu assez de rep pour commenter.

9
Simon Lippens

Comme @Sharppoint l'a dit dans des commentaires, j'ai résolu le problème en supprimant @JsonManagedReference MAIS conserver @JsonBackReference.

8
Benjamin Lucidarme

Vous avez besoin d'une annotation @ResponseBody comme suit:

@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

J'avais le même bogue et j'ai résolu de supprimer toutes mes annotations @JsonBackReference et @JsonManagedReference, puis j'ai mis @JsonIdentityInfo dans tous mes classements avec des relations Consultez la Documentation

0
Lupita Llamas