1

帮助!试图通过 Rest (Jersey) 实现协议缓冲区,但得到这个异常。

class com.util.ProtobufMessageBodyReader
class com.util.ProtobufMessageBodyWriter
Jul 6, 2010 3:43:37 PM org.apache.coyote.http11.Http11Protocol start
INFO: Starting Coyote HTTP/1.1 on http-9102
Jul 6, 2010 3:43:37 PM org.apache.catalina.startup.Catalina start
INFO: Server startup in 45485 ms
Jul 6, 2010 3:49:00 PM org.apache.catalina.connector.CoyoteAdapter convertURI
SEVERE: Invalid URI encoding; using HTTP default
Jul 6, 2010 3:49:00 PM com.sun.jersey.spi.container.ContainerRequest getEntity
SEVERE: A message body reader for Java type, class com.example.tutorial.ProfileRequestProto$ProfileRequest, and MIME media type, application/x-protobuf, was not found

我在 Apache ContextLoader 中加载了 ProtobufMessageBodyReader/Writer。从上面的日志中,似乎 Tomcat 找到了该类,但它在读取时显然失败了

 @Consumes("application/x-protobuf")

这是 ProtobufMessageBodyReader

@Provider
 @Component
 @Consumes("application/x-protobuf")
    public class ProtobufMessageBodyReader implements MessageBodyReader<Message> {

     public boolean isReadable(Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) {
         return Message.class.isAssignableFrom(type);
     }

     public Message readFrom(Class<Message> type, Type genericType, Annotation[] annotations,
                 MediaType mediaType, MultivaluedMap<String, String> httpHeaders, 
                 InputStream entityStream) throws IOException, WebApplicationException {
         try {
             Method newBuilder = type.getMethod("newBuilder");
             GeneratedMessage.Builder<?> builder = (GeneratedMessage.Builder<?>) newBuilder.invoke(type);
             return builder.mergeFrom(entityStream).build();
         } catch (Exception e) {
             throw new WebApplicationException(e);
         }
     }

  @Override
  public boolean isReadable(Class<?> arg0, Type arg1, Annotation[] arg2) {
   // TODO Auto-generated method stub
   return false;
  }

这里是 ProtobufMessageBodyWriter

@Provider
 @Component
 @Produces("application/x-protobuf")
 public class ProtobufMessageBodyWriter implements MessageBodyWriter<Message> {

     public boolean isWriteable(Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) {
         return Message.class.isAssignableFrom(type);
     }

     public long getSize(Message m, Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) {
      return m.getSerializedSize();
     }

     public void writeTo(Message m, Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType, MultivaluedMap<String,Object> httpHeaders,OutputStream entityStream) throws IOException, WebApplicationException {
         entityStream.write(m.toByteArray());
     }

这是来自客户端的代码:

URL url = new URL(URL);
   HttpURLConnection http = (HttpURLConnection)url.openConnection();
   http.setDoInput(true);
   http.setDoOutput(true);
   http.setUseCaches(false);  
         http.setRequestMethod("POST");
         http.setRequestProperty("Content-Type","application/x-protobuf");
         http.setRequestProperty("Accept", "application/x-protobuf");

         DataOutputStream stream = new DataOutputStream(http.getOutputStream ());

         if(contentType.equals("application/x-protobuf")) {
          ProfileRequest.Builder profile = ProfileRequest.newBuilder();
          profile.setName("John");
          profile.setId("123");
          profile.build().writeTo(http.getOutputStream());
         }

         stream.flush();
         stream.close();

这是来自服务器的代码

 @POST
    @Consumes("application/x-protobuf")
     public byte[] processProtoRequest(ProfileRequest protoRequest) {

     byte[] result = null;     
     ProfileRequest.Builder profile = ProfileRequest.newBuilder();
     profile.mergeFrom(protoRequest);                  
     result  = getProfileProtoResponse(profile); 

        }catch(Exception e){
         }

        return result;
    }

我无法弄清楚是什么问题。泽西配置有什么东西吗?或者当我通过 HTTP 发送协议请求时出现问题?

任何帮助将不胜感激。

谢谢

4

2 回答 2

2

我认为你自己已经解决了这个问题:

并且未找到 MIME 媒体类型 application/x-protobuf
[...]

从上面的日志中,似乎 Tomcat 找到了该类,但它在读取时显然失败了 @Consumes("application/x-protobuf")

Jersey(或者更确切地说是JSR-311/JAX-RS)开箱即用支持的媒体类型在MediaType 类中定义。要解决您的问题,为 定义适当的媒体类型可能就足够了application/x-protobuf,请参阅线程[Jersey] MediaType-s? 有关此的讨论和示例。

于 2010-07-25T19:19:47.583 回答
0

我刚刚在我的 maven+jersey+protobuf 项目中遇到了同样的问题,我正在使用 tomcat 6。对我来说,问题是 tomcat 没有找到提供程序类。在我解决了这个问题之后,tomcat 6.0 显示如下:

 Deploying configuration descriptor jerseydemo2.xml
一月 26, 2015 11:13:41 上午 com.sun.jersey.api.core.WebAppResourceConfig init
信息: Scanning for root resource and provider classes in the Web app resource paths:
  /WEB-INF/lib
  /WEB-INF/classes
一月 26, 2015 11:13:41 上午 com.sun.jersey.api.core.ScanningResourceConfig logClasses
信息: Root resource classes found:
  class sample.hello.resources.AddressBookResource
一月 26, 2015 11:13:41 上午 com.sun.jersey.api.core.ScanningResourceConfig logClasses
信息: Provider classes found:
  class sample.pb.ProtobufMessageBodyReader
  class sample.pb.ProtobufMessageBodyWriter
一月 26, 2015 11:13:41 上午 com.sun.jersey.server.impl.application.WebApplicationImpl initiate
信息: Initiating Jersey application, version 'Jersey: 1.2-SNAPSHOT 01/27/2010 01:47 AM'

在它显示未找到提供程序类之前。

我的问题是 web.xml 文件已经为 tomcat 设置了特定路径来查找所有资源。现在我已经改变了它:

<?xml version="1.0" encoding="UTF-8"?>

<web-app xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
    version="2.5">
    <servlet>
        <servlet-name>ServletAdaptor</servlet-name>
        <servlet-class>com.sun.jersey.server.impl.container.servlet.ServletAdaptor</servlet-class>
        <load-on-startup>1</load-on-startup>
    </servlet>

    <servlet-mapping>
        <servlet-name>ServletAdaptor</servlet-name>
        <url-pattern>/rest/*</url-pattern>
    </servlet-mapping>

</web-app>

希望对你有帮助!

于 2015-01-26T19:31:43.247 回答