【问题标题】:AngularJS Client, JAX-RS Jersey Rest Service - application/json client request throwing 'Error parsing media type'AngularJS 客户端,JAX-RS Jersey Rest 服务 - 应用程序/json 客户端请求抛出“解析媒体类型错误”
【发布时间】:2013-08-02 02:43:31
【问题描述】:

我正在使用以下 AngularJS 客户端代码向球衣休息服务执行带有 JSON 格式有效负载的 HTTP 发布请求

patientMgmtModule.controller('NewPatientCtrl',
function NewPatientCtrl($scope, $http)
{
    $scope.addPatient = function (){

    var patientJSON = angular.toJson($scope.Patient);
    console.log("Patient (JSON) is ============> " + patientJSON);

    $http({
      method: 'POST',
      data: $scope.Patient,
      url:'/ManagePatient/AddPatient',
      headers: {'Content-Type':'application/x-www-form-urlencoded;application/json;'}
    });
};

} );

我对 Jersey 有以下 maven 依赖项:

 <dependency>
    <groupId>org.glassfish.jersey.archetypes</groupId>
    <artifactId>jersey-quickstart-webapp</artifactId>
    <version>2.0</version>
  </dependency>
  <dependency>
    <groupId>org.glassfish.jersey.containers</groupId>
    <artifactId>jersey-container-servlet-core</artifactId>
    <version>2.0</version>
  </dependency>

在服务器端,我有

import javax.ws.rs.Consumes;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import com.hms.app.ui.beans.Patient;

@Path("/ManagePatient")
public class PatientController {

  @POST
  @Path("/AddPatient")
  @Consumes({MediaType.APPLICATION_JSON})
  public String addPatient(Patient patient) {
    System.out.println("Sarat's servlet called" );
    //patient.toConsole();
    System.out.println("Done Calling Patient To Console");
    return "Done Calling Patient To Console";
  } 
}

当我在客户端提交表单时,我在 chrome 控制台中看到以下错误 -

POST http://localhost:8080/HMS_Web/services/ManagePatient/AddPatient 500 (Internal Server Error) angular.min.js:99

在服务器端,我看到了(高级细节 1):

SEVERE: Servlet.service() for servlet [Jersey REST Service] in context with path [/HMS_Web] threw exception
org.glassfish.jersey.message.internal.HeaderValueException: Unable to parse "Content-Type" header value: "application/x-www-form-urlencoded;application/json;"

最后的堆栈跟踪是这样的:

Caused by: java.text.ParseException: Expected separator '=' instead of '/'

详细的堆栈跟踪:(

Aug 01, 2013 9:28:18 PM org.apache.catalina.core.StandardWrapperValve invoke
SEVERE: Servlet.service() for servlet [Jersey REST Service] in context with path [/HMS_Web] threw exception
org.glassfish.jersey.message.internal.HeaderValueException: Unable to parse "Content-Type" header value: "application/x-www-form-urlencoded;application/json;"
at org.glassfish.jersey.message.internal.InboundMessageContext.exception(InboundMessageContext.java:318)
at org.glassfish.jersey.message.internal.InboundMessageContext.singleHeader(InboundMessageContext.java:313)
at org.glassfish.jersey.message.internal.InboundMessageContext.getMediaType(InboundMessageContext.java:427)
at org.glassfish.jersey.servlet.WebComponent.filterFormParameters(WebComponent.java:482)
at org.glassfish.jersey.servlet.WebComponent.service(WebComponent.java:303)
at org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:372)
at org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:335)
at org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:218)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:305)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:222)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:123)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:472)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:168)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:99)
at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:929)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:407)
at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1002)
at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:585)
at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:312)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1110)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:603)
at java.lang.Thread.run(Thread.java:722)
Caused by: javax.ws.rs.ProcessingException: java.lang.IllegalArgumentException: Error parsing media type 'application/x-www-form-urlencoded;application/json;'
at org.glassfish.jersey.message.internal.InboundMessageContext$5.apply(InboundMessageContext.java:433)
at org.glassfish.jersey.message.internal.InboundMessageContext$5.apply(InboundMessageContext.java:427)
at org.glassfish.jersey.message.internal.InboundMessageContext.singleHeader(InboundMessageContext.java:311)
... 22 more
Caused by: java.lang.IllegalArgumentException: Error parsing media type 'application/x-www-form-urlencoded;application/json;'
at org.glassfish.jersey.message.internal.MediaTypeProvider.fromString(MediaTypeProvider.java:89)
at org.glassfish.jersey.message.internal.MediaTypeProvider.fromString(MediaTypeProvider.java:59)
at javax.ws.rs.core.MediaType.valueOf(MediaType.java:179)
at org.glassfish.jersey.message.internal.InboundMessageContext$5.apply(InboundMessageContext.java:431)
... 24 more
Caused by: java.text.ParseException: Expected separator '=' instead of '/'
at org.glassfish.jersey.message.internal.HttpHeaderReader.nextSeparator(HttpHeaderReader.java:115)
at org.glassfish.jersey.message.internal.HttpHeaderReader.readParameters(HttpHeaderReader.java:261)
at org.glassfish.jersey.message.internal.HttpHeaderReader.readParameters(HttpHeaderReader.java:242)
at org.glassfish.jersey.message.internal.MediaTypeProvider.valueOf(MediaTypeProvider.java:107)
at org.glassfish.jersey.message.internal.MediaTypeProvider.fromString(MediaTypeProvider.java:87)
... 27 more

Aug 01, 2013 9:29:00 PM org.apache.catalina.core.StandardWrapperValve invoke
SEVERE: Servlet.service() for servlet [Jersey REST Service] in context with path [/HMS_Web] threw exception
org.glassfish.jersey.message.internal.HeaderValueException: Unable to parse "Content-Type" header value: "application/x-www-form-urlencoded;application/json;"
at org.glassfish.jersey.message.internal.InboundMessageContext.exception(InboundMessageContext.java:318)
at org.glassfish.jersey.message.internal.InboundMessageContext.singleHeader(InboundMessageContext.java:313)
at org.glassfish.jersey.message.internal.InboundMessageContext.getMediaType(InboundMessageContext.java:427)
at org.glassfish.jersey.servlet.WebComponent.filterFormParameters(WebComponent.java:482)
at org.glassfish.jersey.servlet.WebComponent.service(WebComponent.java:303)
at org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:372)
at org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:335)
at org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:218)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:305)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:222)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:123)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:472)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:168)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:99)
at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:929)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:407)
at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1002)
at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:585)
at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:312)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1110)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:603)
at java.lang.Thread.run(Thread.java:722)
Caused by: javax.ws.rs.ProcessingException: java.lang.IllegalArgumentException: Error parsing media type 'application/x-www-form-urlencoded;application/json;'
at org.glassfish.jersey.message.internal.InboundMessageContext$5.apply(InboundMessageContext.java:433)
at org.glassfish.jersey.message.internal.InboundMessageContext$5.apply(InboundMessageContext.java:427)
at org.glassfish.jersey.message.internal.InboundMessageContext.singleHeader(InboundMessageContext.java:311)
... 22 more
Caused by: java.lang.IllegalArgumentException: Error parsing media type 'application/x-www-form-urlencoded;application/json;'
at org.glassfish.jersey.message.internal.MediaTypeProvider.fromString(MediaTypeProvider.java:89)
at org.glassfish.jersey.message.internal.MediaTypeProvider.fromString(MediaTypeProvider.java:59)
at javax.ws.rs.core.MediaType.valueOf(MediaType.java:179)
at org.glassfish.jersey.message.internal.InboundMessageContext$5.apply(InboundMessageContext.java:431)
... 24 more
Caused by: java.text.ParseException: Expected separator '=' instead of '/'
at org.glassfish.jersey.message.internal.HttpHeaderReader.nextSeparator(HttpHeaderReader.java:115)
at org.glassfish.jersey.message.internal.HttpHeaderReader.readParameters(HttpHeaderReader.java:261)
at org.glassfish.jersey.message.internal.HttpHeaderReader.readParameters(HttpHeaderReader.java:242)
at org.glassfish.jersey.message.internal.MediaTypeProvider.valueOf(MediaTypeProvider.java:107)
at org.glassfish.jersey.message.internal.MediaTypeProvider.fromString(MediaTypeProvider.java:87)
... 27 more

实施 LoggingFilter 后 - 我看到服务器正在响应 HTTP 415。

Aug 04, 2013 10:28:25 AM org.glassfish.jersey.filter.LoggingFilter log
INFO: 2 * LoggingFilter - Request received on thread tomcat-http--11
2 > POST http://localhost:8080/HMS_Web/services/ManagePatient/AddPatient
2 > host: localhost:8080
2 > connection: keep-alive
2 > content-length: 341
2 > accept: application/json, text/plain, */*
2 > origin: http://localhost:8080
2 > x-requested-with: XMLHttpRequest
2 > user-agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/28.0.1500.72 Safari/537.36
2 > content-type: application/json
2 > dnt: 1
2 > referer: http://localhost:8080/HMS_Web/views/Landing.html
2 > accept-encoding: gzip,deflate,sdch
2 > accept-language: en-US,en;q=0.8

Aug 04, 2013 10:28:25 AM org.glassfish.jersey.filter.LoggingFilter log
INFO: 2 * LoggingFilter - Response received on thread tomcat-http--11
2 < 415

【问题讨论】:

    标签: angularjs jax-rs jersey-2.0


    【解决方案1】:

    您的 Content-Type 标头无效(请参阅规范 14.17 Content-Type)。根据您的 JAX-RS 资源,您应该使用 application/json 作为 Content-Type(没有 application/x-www-form-urlencoded):

    $http({
      method: 'POST',
      data: $scope.Patient,
      url:'/ManagePatient/AddPatient',
      headers: {'Content-Type':'application/json'}
    });
    

    编辑 1:

    如果您想查看到达您服务器的请求,您可以注册LoggingFilter,它会向您显示一些有用的信息。您可以在以下位置开启它:

    web.xml(将其添加到 JAX-RS servlet 定义中):

    <init-param>
        <param-name>jersey.config.server.provider.classnames</param-name>
        <param-value>org.glassfish.jersey.filter.LoggingFilter</param-value>
    </init-param>
    

    Application分机:

    public class MyApplication extends Application {
    
        @Override
        public Set<Class<?>> getClasses() {
            return new HashSet<Class<?>>() {{
                // Add your resources.
                add(HelloWorldResource.class);
    
                // Add LoggingFilter.
                add(LoggingFilter.class);
            }};
        }
    }
    

    ResourceConfig 实例(演示也在这里输出实体):

    public class MyApplication extends ResourceConfig {
    
        public MyApplication() {
            // Resources - add your package name here to enable package scanning.
            packages(...);
    
            // Enable LoggingFilter & output entity.     
            registerInstances(new LoggingFilter(Logger.getLogger(MyApplication.class.getName()), true));
        }
    }
    

    编辑 2:

    Jersey 2.x 不支持开箱即用的 application/json 媒体类型 - 您需要将其中一个 JSON 模块添加到您的类路径(请参阅用户指南中的 JSON 部分),例如:

    <dependency>
        <groupId>org.glassfish.jersey.media</groupId>
        <artifactId>jersey-media-moxy</artifactId>
        <version>2.0</version>
    </dependency>
    

    【讨论】:

    • 但没有 (application/x-www-form-urlencoded) - 来自 Angular js 客户端的请求不会作为 json 请求发布到服务器端......它被发布为文本/html。
    • 你为什么会这样认为?您可以尝试将 LoggingFilter 注册到您的 Jersey 2.x 应用程序中以查看从 JS 客户端发送的标头吗?
    • 我正在尝试将 LoggingFilter 添加为 specified here...但这似乎不起作用!试图弄清楚如何为泽西岛实现 LoggingFilter .. 感谢您的指导!
    • 查看答案,了解如何在 Jersey 2.x 中注册 LoggingFilter
    • 感谢 v.v.v.v.much 的帮助...我能够配置 LoggingFilter。我看到请求被发布到服务器并且服务器正在响应 http 代码 415。(使用此信息更新了问题)...试图弄清楚如何解决它。
    猜你喜欢
    • 1970-01-01
    • 2016-12-06
    • 2023-04-04
    • 1970-01-01
    • 2013-06-03
    • 1970-01-01
    • 2015-07-20
    • 1970-01-01
    • 2015-04-03
    相关资源
    最近更新 更多