2010-07-06 61 views
1

說明! 嘗試通過Rest(Jersey)實現協議緩衝區,但得到此異常。協議緩衝區MIME問題

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發送協議請求時出現錯誤?

任何幫助將不勝感激。

感謝

+0

將內容類型設置爲「application/octet-stream」 http://stackoverflow.com/questions/1425912/google-protocol-buffers-and-http – fjjiaboming 2012-01-04 08:07:35

回答

2

你自己大多已釘這個問題,我認爲:

和MIME媒體類型,應用程序/ x-protobuf的,沒有被發現
[...]

從上面的日誌看來,Tomcat發現了這個類,但它顯示它在讀取時顯示失敗 @Consumes("application/x-protobuf")

開箱即用Jersey(或更確切地說JSR-311/JAX-RS)支持的媒體類型在class MediaType中定義。要解決您的問題,可能需要爲application/x-protobuf定義適當的媒體類型,請參閱線索[Jersey] MediaType-s?以獲取關於此的討論和示例。

0

我剛剛在我的maven + jersey + protobuf項目中遇到了同樣的問題,而且我正在使用tomcat 6.對我來說問題在於Tomcat的Provider類未找到。 後,我解決這個問題的是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> 

希望它可以幫助你!