2015-04-22 2 views
0

Lorsque j'utilise un FeignClient il donne le Content-Type à application/x-www-form-urlencoded au lieu de application/json;charset=UTF-8.Printemps/Eureka/Feindre - la mise en FeignClient tête Content-Type application/x-www-form-urlencoded

Si j'utilise un RestTemplate pour envoyer le même message, l'en-tête de message Content-Type est correctement défini sur application/json;charset=UTF-8.

Les deux FeignClient et RestTemplate utilisent Eureka pour la découverte de service, et j'ai découvert ce problème en déboguant le message HTTP reçu par le serveur.

Le contrôleur du côté du serveur ressemble à ceci:

@RestController 
@RequestMapping("/site/alarm") 
public class SiteAlarmController { 
    @RequestMapping(method = RequestMethod.POST) 
    @ResponseBody 
    public ResponseEntity<RaiseAlarmResponseDto> raiseAlarm(@RequestBody RaiseSiteAlarmRequestDto requestDto) { 
     ... 
    } 

mon interface FeignClient au service qui appelle l'alarme ressemble à ceci:

@FeignClient("alarm-service") 
public interface AlarmFeignService { 
    @RequestMapping(method = RequestMethod.POST, value = "/site/alarm") 
    RaiseAlarmResponseDto raiseAlarm(@RequestBody RaiseSiteAlarmRequestDto requestDto); 
} 

Les en-têtes de message HTTP de la FeignClient sont :

Accept: */* 
Cache-Control: no-cache 
Pragma: no-cache 
User-Agent: Java/1.7.0_60 
Host: smit005s-MacBook-Pro.local:9120 
Connection: keep-alive 
Content-Type: application/x-www-form-urlencoded 
Content-Length: 323 

Le service d'alarme n'est pas disponible « Aime le Content-Type et jette l'exception suivante:

2015-04-22 12:12:28.580 thread="qtp1774842986-25" class="org.eclipse.jetty.servlet.ServletHandler" level="WARN" 
org.springframework.web.util.NestedServletException: Request processing failed; nested exception is feign.FeignException: status 415 reading AlarmFeignService#raiseAlarm(RaiseSiteAlarmRequestDto); content: 
{"timestamp":1429701148576,"status":415,"error":"Unsupported Media Type","exception":"org.springframework.web.HttpMediaTypeNotSupportedException","message":"Unsupported Media Type","path":"/site/alarm"} 
    at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:978) ~[spring-webmvc-4.1.5.RELEASE.jar:4.1.5.RELEASE] 
    at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:857) ~[spring-webmvc-4.1.5.RELEASE.jar:4.1.5.RELEASE] 
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:618) ~[tomcat-embed-core-8.0.20.jar:8.0.20] 
    ... 
    ... /* commented rest of stack out */ 
    ... 

Si je change le code côté client d'utiliser un RestTemplate comme suit:

@Service 
public class AlarmService { 
    @Autowired 
    private RestTemplate restTemplate; 
... 
    public void send(RaiseSiteAlarmRequestDto alarm) { 
     RaiseAlarmResponseDto result = restTemplate.postForObject("http://alarm-service/site/alarm", 
      raiseSiteAlarmRequestDto, RaiseAlarmResponseDto.class); 
    } 
} 

Il fonctionne avec le RestTemplate, le alarm-service reçoit le message et le traite avec succès. Les en-têtes de messages envoyés par le RestTemplate sont:

Accept: application/json, application/*+json 
Content-Type: application/json;charset=UTF-8 
Cache-Control: no-cache 
Pragma: no-cache 
User-Agent: Java/1.7.0_60 
Host: smit005s-MacBook-Pro.local:9120 
Connection: keep-alive 
Content-Length: 323 
+0

Avez-vous essayé d'abandonner le 'ResponseEntity ' de votre contrôleur pour tester si cela interférait avec le client Feign? Mon autre supposition est que Feign n'est pas capable de désérialiser votre objet 'RaiseAlarmResponseDto'. – jebeaudet

+0

Le '@ RequestBody' sur' @ FeignClient' ne fait rien. Pouvez-vous faire un appel réussi sans feindre, mais avec eureka? – spencergibb

+0

Merci @spencergibb c'était une bonne suggestion. Le changer en RestTemplate fonctionne, et c'est découvrir le service à travers Eureka.Lorsque je mets le débogage du côté du récepteur, je peux voir que le client feign l'envoie avec l'en-tête 'Content-Type' incorrectement à' application/x-www-form-urlencoded'. Alors que 'RestTemplate' définit le' Content-Type' à 'application/json; charset = UTF-8'. Je vais mettre à jour la question avec ça. – user1232555

Répondre

7

La réponse était de faire comme @spencergibb suggère; utilisez la directive consumes dans l'annotation @RequestMapping sur l'interface FeignClient. Ce Spring/Netflix documentaition a également un exemple.

Ainsi, par exemple la déclaration d'interface @FeignClient dans le client est maintenant:

@FeignClient("alarm-service") 
public interface AlarmFeignService { 
    @RequestMapping(method = RequestMethod.POST, value = "/site/alarm", consumes = "application/json")) 
    RaiseAlarmResponseDto raiseAlarm(RaiseSiteAlarmRequestDto requestDto); 
} 

RemarqueCet est seulement nécessaire sur le côté client et le contrôleur côté serveur n'a pas besoin d'avoir ce changement.

serait bien si cela a été fait par défaut sur le @FeignClient et il serait alors compatible avec la RestTemplate et le contrôleur côté serveur annotation @RequestMapping. Peut-être que cela peut être fait dans une future version de spring-cloud.

+0

Cela ne fonctionne pas pour l'application/x-www-form-urlencoded vous obtiendrez: feign.codec.EncodeException: Impossible d'écrire la requête: non HttpMessageConverter trouvé pour le type de requête [com. *. Pojos.OAuthLoginPojo] et le type de contenu [ application/x-www-form-urlencoded] –