web-dev-qa-db-fra.com

POST JSON échoue avec le type de support 415 non pris en charge, Spring 3 mvc

J'essaie d'envoyer une demande POST à un servlet. La requête est envoyée via jQuery de la manière suivante:

var productCategory = new Object();
productCategory.idProductCategory = 1;
productCategory.description = "Descrizione2";
newCategory(productCategory);

où newCategory est

function newCategory(productCategory)
{
  $.postJSON("ajax/newproductcategory", productCategory, function(
      idProductCategory)
  {
    console.debug("Inserted: " + idProductCategory);
  });
}

et postJSON est

$.postJSON = function(url, data, callback) {
    return jQuery.ajax({
    'type': 'POST',
    'url': url,
    'contentType': 'application/json',
    'data': JSON.stringify(data),
    'dataType': 'json',
    'success': callback
    });
};

Avec firebug, je vois que JSON est envoyé correctement:

{"idProductCategory":1,"description":"Descrizione2"}

Mais je reçois 415 types de support non supportés. Contrôleur mvc de printemps a la signature

    @RequestMapping(value = "/ajax/newproductcategory", method = RequestMethod.POST)
public @ResponseBody
Integer newProductCategory(HttpServletRequest request,
        @RequestBody ProductCategory productCategory)

Il y a quelques jours, cela a fonctionné, maintenant ce n'est pas le cas. Je montrerai plus de code si nécessaire . Merci

146
gc5

J'ai réussi à le faire fonctionner. Dites-moi si je me trompe ... J'ai utilisé un seul moyen de sérialiser/désérialiser: j'ai supprimé toutes les annotations concernant ceci (@JSONSerialize et @JSONDeserialize) et j'ai enregistré des sérialiseurs et des desaliseurs dans la classe CustomObjectMapper . Je n'ai pas trouvé article expliquant ce comportement mais j'ai résolu de cette façon. J'espère que c'est utile.

3
gc5

Cela s'est déjà produit avec Spring @ResponseBody et c'est parce qu'aucun en-tête d'acceptation n'a été envoyé avec la demande. Accepter en-tête peut être difficile à définir avec jQuery, mais cela a fonctionné pour moi source

$.postJSON = function(url, data, callback) {
    return jQuery.ajax({
    headers: { 
        'Accept': 'application/json',
        'Content-Type': 'application/json' 
    },
    'type': 'POST',
    'url': url,
    'data': JSON.stringify(data),
    'dataType': 'json',
    'success': callback
    });
};

L'en-tête Content-Type est utilisé par @RequestBody pour déterminer le format des données envoyées par le client dans la demande. L'en-tête d'acceptation est utilisé par @ResponseBody pour déterminer le format dans lequel les données doivent être renvoyées au client dans la réponse. C'est pourquoi vous avez besoin des deux en-têtes.

217
theon

J'avais un problème similaire, mais le problème était que j'avais négligé de fournir un constructeur par défaut pour le DTO annoté avec @RequestBody.

18
John Shepherd

Je crois avoir rencontré exactement le même problème. Après d'innombrables heures de combat avec le JSON, le JavaScript et le serveur, j'ai trouvé le coupable: dans mon cas, j'avais un objet Date dans le DTO, cet objet Date a été converti en chaîne afin que nous puissions le montrer dans la vue avec le format: HH: mm.

Lorsque les informations JSON étaient renvoyées, cet objet Date String devait être reconverti en un objet Date complet. Par conséquent, nous avons également besoin d'une méthode pour le définir dans le DTO. Le gros MAIS est que vous ne pouvez pas avoir 2 méthodes portant le même nom (Surcharge) dans le DTO, même si elles ont un type de paramètre différent (String vs Date), car cela vous donnera également l'erreur de type de support 415 non pris en charge.

C'était ma méthode de contrôle

  @RequestMapping(value = "/alarmdownload/update", produces = "application/json", method = RequestMethod.POST)
  public @ResponseBody
  StatusResponse update(@RequestBody AlarmDownloadDTO[] rowList) {
    System.out.println("hola");
    return new StatusResponse();
  }

Voici mon exemple DTO (id get/set et preAlarm get Les méthodes ne sont pas incluses pour la brièveté du code):

@JsonIgnoreProperties(ignoreUnknown = true)
public class AlarmDownloadDTO implements Serializable {

  private static final SimpleDateFormat formatHHmm = new SimpleDateFormat("HH:mm");

  private String id;
  private Date preAlarm;

  public void setPreAlarm(Date date) { 
    this.preAlarm == date;
  }
  public void setPreAlarm(String date) {    
    try {
      this.preAlarm = formatHHmm.parse(date);
    } catch (ParseException e) {
      this.preAlarm = null;
    } catch (NullPointerException e){
      this.preAlarm = null;
    }
  }
}

Pour que tout fonctionne, vous devez supprimer la méthode avec le paramètre de type Date. Cette erreur est très frustrante. J'espère que cela peut sauver des heures de débogage à quelqu'un.

11
will824

l'ajout du type de contenu dans la demande en tant que application/json a résolu le problème

11
uiroshan

J'ai fait face à un problème similaire et voici comment je l'ai corrigé,

Le problème est dû au processus de conversion de JSON à Java, il est nécessaire d’avoir les bonnes bibliothèques d’exécution pour que la conversion se déroule correctement.

Ajoutez les fichiers JAR suivants (par dépendance ou en les téléchargeant et en les ajoutant au classpath.

<dependency>
<groupId>org.codehaus.jackson</groupId>
<artifactId>jackson-mapper-asl</artifactId>
<version>1.9.13</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.5.3</version>
</dependency>

Cela devrait résoudre le problème. 

Code complet:

function() {
  $.ajax({
    type: "POST",
    url: "saveUserDetails.do",
    data: JSON.stringify({
      name: "Gerry",
      ity: "Sydney"
    }),
    headers: {
      'Accept': 'application/json',
      'Content-Type': 'application/json'
    },
    success: function(data) {
      if (data.status == 'OK')
        alert('Person has been added');
      else
        alert('Failed adding person: ' + data.status + ', ' + data.errorMessage);
}

et la signature du contrôleur ressemble à ceci:

@RequestMapping(value = "/saveUserDetails.do", method = RequestMethod.POST)
public @ResponseBody Person addPerson( @RequestBody final  Person person) {

J'espère que cela t'aides

9
vinSan

J'ai fait face à ce problème lorsque j'ai intégré Spring Boot avec Spring MVC. Je l'ai résolu en ajoutant simplement ces dépendances.

<dependency>
<groupId>org.codehaus.jackson</groupId>
<artifactId>jackson-mapper-asl</artifactId>
<version>1.9.13</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.5.3</version>
</dependency>
8
deep

Une petite note latérale - est tombé sur cette même erreur lors du développement d'une application Web. L'erreur que nous avons trouvée, en jouant avec le service avec Firefox Poster, était que les champs et les valeurs du Json devaient être entourés de guillemets doubles. Par exemple..

[ {"idProductCategory" : "1" , "description":"Descrizione1"}, 
  {"idProductCategory" : "2" , "description":"Descrizione2"} ]

Dans notre cas, nous avons rempli le json via javascript, ce qui peut être un peu déroutant quand il s'agit de traiter avec des guillemets simples/doubles, d'après ce que j'ai entendu.

Ce qui a déjà été dit dans cet article et d'autres, comme l'inclusion des en-têtes "Accept" et "Content-Type", s'applique également.

J'espère qu'ils vont.

5
Carlos Romero

J'ai eu le même problème. J'ai dû suivre ces étapes pour résoudre le problème:

1. Assurez-vous que vous avez les dépendances suivantes:

    <dependency>
        <groupId>com.fasterxml.jackson.core</groupId>
        <artifactId>jackson-core</artifactId>
        <version>${jackson-version}</version> // 2.4.3
    </dependency>
    <dependency>
        <groupId>com.fasterxml.jackson.core</groupId>
        <artifactId>jackson-databind</artifactId>
        <version>${jackson-version}</version> // 2.4.3
    </dependency>

2. Créez le filtre suivant:

    public class CORSFilter extends OncePerRequestFilter {

        @Override
        protected void doFilterInternal(HttpServletRequest request,
                                        HttpServletResponse response, FilterChain filterChain)
                throws ServletException, IOException {

            String Origin = request.getHeader("Origin");
            Origin = (Origin == null || Origin.equals("")) ? "null" : Origin;
            response.addHeader("Access-Control-Allow-Origin", Origin);
            response.addHeader("Access-Control-Allow-Methods", "POST, GET, PUT, UPDATE, DELETE, OPTIONS");
            response.addHeader("Access-Control-Allow-Credentials", "true");
            response.addHeader("Access-Control-Allow-Headers",
                    "Authorization, Origin, content-type, accept, x-requested-with");

            filterChain.doFilter(request, response);
        }
    }

3. Appliquez le filtre ci-dessus pour les demandes dans web.xml

    <filter>
        <filter-name>corsFilter</filter-name>
        <filter-class>com.your.package.CORSFilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>corsFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

J'espère que cela est utile à quelqu'un.

1
Manoj Shrestha

J'ai résolu ce problème en ajoutant la liaison de données jackson-json à mon pom.

<dependency>
        <groupId>com.fasterxml.jackson.core</groupId>
        <artifactId>jackson-databind</artifactId>
        <version>2.6.3</version>
</dependency>
0
Lingasamy Bagavathi

Botte de printemps + printemps mvn

avec problème @ PostMapping ("/ addDonation") public String addDonation (@RequestBody DonatorDTO donatorDTO) {

avec solution @RequestMapping (value = "/ addDonation", method = RequestMethod.POST) @ResponseBody public GenericResponse addDonation (final DonatorDTO donatorDTO, demande finale HttpServletRequest) {

0