2014-09-23 2 views
1

Итак, я искал всю эту сеть для этого, но не мог найти, почему этот не работает. Я до сих пор довольно далеко, думаю, я просто застрял в этой очень странной проблеме.Тестирование множественного/связанного запроса POST с UrlConnection - Не удалось найти границу MIME: - the_photo

Я создал веб-сервис CXF, который позволяет людям загружать фотографии (для развертывания в Google Apps Engine). Он должен работать нормально, но: я не знаю, как это проверить, поскольку он многочастен/связан (так же как и контракт). Невозможно протестировать это через PostMan, SOAPUI или любой другой тестер UI, поэтому я сразу же пошел на тестирование с Java.

Я начал из этой статьи: http://www.jguru.com/faq/view.jsp?EID=735674, и прошли через эти примеры того, как мой синтаксис должен выглядеть следующим образом:

Heck , Я даже прошел через исходный код Apache CXF, чтобы найти источник сбоя здесь GC - AttachmentDeserializer ,

Это то, что я хочу отправить:

--the_photo 
Content-Type: application/json 

{ 
    "objectToLinkTo": "ad9821e6-d308-472b-b21f-308b08c3fa70" 
} 

--the_photo 
Content-Type: image/jpeg 

JPEG data 

--the_photo-- 

Это то, что я делаю, чтобы попробовать отправить это:

import java.io.BufferedInputStream; 
import java.io.DataOutputStream; 
import java.io.InputStream; 
import java.net.URL; 
import java.net.URLConnection; 
import java.nio.file.Files; 
import java.nio.file.Paths; 

public class PhotoTest { 
    private static final String ADD_PHOTO = "http://localhost:8080/v1/photos"; 

    private static void writeJson(String value, DataOutputStream out, String boundary) { 
     try { 
      out.writeBytes("Content-Type: application/json"); 
      out.writeBytes("\n{'objectToLinkTo': '" + value + "'}"); 
      out.writeBytes("\n--" + boundary); 
     } catch (Exception e) { 
      e.printStackTrace(); 
     } 
    } 

    private static void writeImage(String contentType, String file, DataOutputStream out, String boundary) { 
     try { 
      out.writeBytes("Content-Type: " + contentType + "\n"); 
      java.nio.file.Path path = Paths.get(file); 
      byte[] data = Files.readAllBytes(path); 
      out.write(data); 
      out.writeBytes("\n--" + boundary + "--"); 
     } catch (Exception e) { 
      e.printStackTrace(); 
     } 
    } 

    public static void main (String args[]) { 
     try { 
      URL servlet = new URL(ADD_PHOTO); 
      URLConnection urlConnection = servlet.openConnection(); 
      urlConnection.setDoOutput(true); 
      urlConnection.setDoInput(true); 
      urlConnection.setUseCaches(false); 
      String boundary = "the_photo"; 
      urlConnection.setRequestProperty("Content-type", "multipart/related; boundary=" + boundary); 
      urlConnection.setRequestProperty("Cache-Control", "no-cache"); 

      DataOutputStream out = new DataOutputStream(urlConnection.getOutputStream()); 
      out.writeBytes("--" + boundary + "\n"); 
      writeJson("ad9821e6-d308-472b-b21f-308b08c3fa70", out, boundary); 
      writeImage("image/jpeg", "K:\\Downloads\\test.jpg", out, boundary); 
      out.flush(); 
      out.close(); 

      InputStream stream = urlConnection.getInputStream(); 
      BufferedInputStream in = new BufferedInputStream(stream); 
      int i = 0; 
      while ((i = in.read()) != -1) { 
       System.out.write(i); 
      } 
      in.close(); 
     } catch (Exception e) { 
      e.printStackTrace(); 
     } 
    } 
} 

В результате на стороне сервера (код локально развернуты с использованием mvn appengine:test):

[INFO] 07:27:06,804 ERROR [commons.exceptions.exceptionwrapper.RuntimeExceptionWrapper] - Couldn't find MIME boundary: --the_photo 
[INFO] org.apache.cxf.interceptor.Fault: Couldn't find MIME boundary: --the_photo 
[INFO] at org.apache.cxf.interceptor.AttachmentInInterceptor.handleMessage(AttachmentInInterceptor.java:60) 
[INFO] at org.apache.cxf.jaxrs.ext.MessageContextImpl.createAttachments(MessageContextImpl.java:267) 
[INFO] at org.apache.cxf.jaxrs.ext.MessageContextImpl.get(MessageContextImpl.java:76) 
[INFO] at org.apache.cxf.jaxrs.impl.tl.ThreadLocalMessageContext.get(ThreadLocalMessageContext.java:38) 
[INFO] at org.apache.cxf.jaxrs.utils.multipart.AttachmentUtils.getMultipartBody(AttachmentUtils.java:114) 
[INFO] at org.apache.cxf.jaxrs.utils.multipart.AttachmentUtils.getAttachments(AttachmentUtils.java:119) 
[INFO] at org.apache.cxf.jaxrs.provider.MultipartProvider.readFrom(MultipartProvider.java:151) 
[INFO] at org.apache.cxf.jaxrs.utils.JAXRSUtils.readFromMessageBodyReader(JAXRSUtils.java:1325) 
[INFO] at org.apache.cxf.jaxrs.utils.JAXRSUtils.readFromMessageBody(JAXRSUtils.java:1276) 
[INFO] at org.apache.cxf.jaxrs.utils.JAXRSUtils.processParameter(JAXRSUtils.java:815) 
[INFO] at org.apache.cxf.jaxrs.utils.JAXRSUtils.processParameters(JAXRSUtils.java:778) 
[INFO] at org.apache.cxf.jaxrs.interceptor.JAXRSInInterceptor.processRequest(JAXRSInInterceptor.java:212) 
[INFO] at org.apache.cxf.jaxrs.interceptor.JAXRSInInterceptor.handleMessage(JAXRSInInterceptor.java:77) 
[INFO] at org.apache.cxf.phase.PhaseInterceptorChain.doIntercept(PhaseInterceptorChain.java:307) 
[INFO] at org.apache.cxf.transport.ChainInitiationObserver.onMessage(ChainInitiationObserver.java:121) 
[INFO] at org.apache.cxf.transport.http.AbstractHTTPDestination.invoke(AbstractHTTPDestination.java:243) 
[INFO] at org.apache.cxf.transport.servlet.ServletController.invokeDestination(ServletController.java:223) 
[INFO] at org.apache.cxf.transport.servlet.ServletController.invoke(ServletController.java:197) 
[INFO] at org.apache.cxf.transport.servlet.ServletController.invoke(ServletController.java:149) 
[INFO] at org.apache.cxf.transport.servlet.CXFNonSpringServlet.invoke(CXFNonSpringServlet.java:171) 
[INFO] at org.apache.cxf.transport.servlet.AbstractHTTPServlet.handleRequest(AbstractHTTPServlet.java:286) 
[INFO] at org.apache.cxf.transport.servlet.AbstractHTTPServlet.doPost(AbstractHTTPServlet.java:206) 
[INFO] at javax.servlet.http.HttpServlet.service(HttpServlet.java:637) 
[INFO] at org.apache.cxf.transport.servlet.AbstractHTTPServlet.service(AbstractHTTPServlet.java:262) 
[INFO] at org.mortbay.jetty.servlet.ServletHolder.handle(ServletHolder.java:511) 
[INFO] at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1166) 
[INFO] at com.google.appengine.api.socket.dev.DevSocketFilter.doFilter(DevSocketFilter.java:74) 
[INFO] at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157) 
[INFO] at com.google.appengine.tools.development.ResponseRewriterFilter.doFilter(ResponseRewriterFilter.java:127) 
[INFO] at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157) 
[INFO] at com.google.appengine.tools.development.HeaderVerificationFilter.doFilter(HeaderVerificationFilter.java:34) 
[INFO] at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157) 
[INFO] at com.google.appengine.api.blobstore.dev.ServeBlobFilter.doFilter(ServeBlobFilter.java:63) 
[INFO] at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157) 
[INFO] at com.google.apphosting.utils.servlet.TransactionCleanupFilter.doFilter(TransactionCleanupFilter.java:43) 
[INFO] at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157) 
[INFO] at com.google.appengine.tools.development.StaticFileFilter.doFilter(StaticFileFilter.java:125) 
[INFO] at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157) 
[INFO] at com.google.appengine.tools.development.DevAppServerModulesFilter.doDirectRequest(DevAppServerModulesFilter.java:366) 
[INFO] at com.google.appengine.tools.development.DevAppServerModulesFilter.doDirectModuleRequest(DevAppServerModulesFilter.java:349) 
[INFO] at com.google.appengine.tools.development.DevAppServerModulesFilter.doFilter(DevAppServerModulesFilter.java:116) 
[INFO] at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157) 
[INFO] at org.mortbay.jetty.servlet.ServletHandler.handle(ServletHandler.java:388) 
[INFO] at org.mortbay.jetty.security.SecurityHandler.handle(SecurityHandler.java:216) 
[INFO] at org.mortbay.jetty.servlet.SessionHandler.handle(SessionHandler.java:182) 
[INFO] at org.mortbay.jetty.handler.ContextHandler.handle(ContextHandler.java:765) 
[INFO] at org.mortbay.jetty.webapp.WebAppContext.handle(WebAppContext.java:418) 
[INFO] at com.google.appengine.tools.development.DevAppEngineWebAppContext.handle(DevAppEngineWebAppContext.java:98) 
[INFO] at org.mortbay.jetty.handler.HandlerWrapper.handle(HandlerWrapper.java:152) 
[INFO] at com.google.appengine.tools.development.JettyContainerService$ApiProxyHandler.handle(JettyContainerService.java:491) 
[INFO] at org.mortbay.jetty.handler.HandlerWrapper.handle(HandlerWrapper.java:152) 
[INFO] at org.mortbay.jetty.Server.handle(Server.java:326) 
[INFO] at org.mortbay.jetty.HttpConnection.handleRequest(HttpConnection.java:542) 
[INFO] at org.mortbay.jetty.HttpConnection$RequestHandler.content(HttpConnection.java:938) 
[INFO] at org.mortbay.jetty.HttpParser.parseNext(HttpParser.java:755) 
[INFO] at org.mortbay.jetty.HttpParser.parseAvailable(HttpParser.java:218) 
[INFO] at org.mortbay.jetty.HttpConnection.handle(HttpConnection.java:404) 
[INFO] at org.mortbay.io.nio.SelectChannelEndPoint.run(SelectChannelEndPoint.java:409) 
[INFO] at org.mortbay.thread.QueuedThreadPool$PoolThread.run(QueuedThreadPool.java:582) 
[INFO] Caused by: java.io.IOException: Couldn't find MIME boundary: --the_photo 
[INFO] at org.apache.cxf.attachment.AttachmentDeserializer.initializeRootMessage(AttachmentDeserializer.java:123) 
[INFO] at org.apache.cxf.attachment.AttachmentDeserializer.initializeAttachments(AttachmentDeserializer.java:92) 
[INFO] at org.apache.cxf.interceptor.AttachmentInInterceptor.handleMessage(AttachmentInInterceptor.java:58) 
[INFO] ... 58 more 

Итак, я уверен, что код, который я использую для тестирования в основной функции, даже не прошел мимо первого out.writeBytes("--" + boundary + "\n");, так как ошибка указывает, что код сервера не может найти границу где угодно. Я так думаю из-за кода GrepCode, через который я прошел, - это при инициализации сообщения, где-то в AttachmentInInterceptor, что код сбой; поэтому он даже не обрабатывает ничего из фактически записанных данных в потоке. (Или: сервер никогда не достигает моего собственного кода сервера, который проверяет наличие двух вложений и т. Д.).

DataOutputStream out = new DataOutputStream(urlConnection.getOutputStream()); 
out.writeBytes("--" + boundary + "\n"); 
writeJson("ad9821e6-d308-472b-b21f-308b08c3fa70", out, boundary); 
writeImage("image/jpeg", "K:\\Downloads\\test.jpg", out, boundary); 
out.flush(); 
out.close(); 

Любой, кто здесь может помочь мне? Что я делаю не так? Вероятно, это просто деталь, которую я пишу неправильно на urlConnection, что заставляет другой конец провода не найти границу. Но я слишком долго смотрел на это и не могу найти его.


Edit: Так, я сделал некоторые изменения:

Я добавил:

private static final String CRLF = "\r\n"; 
private StringBuilder text = new StringBuilder(); 

И изменилось:

public void writeJson(String value) { 
    String s = "--" + boundary + CRLF; 
    s += "Content-Type: application/json" + CRLF + CRLF; 
    s += "{\"objectToLinkTo\":\"" + value + "\"}" + CRLF + CRLF; 
    text.append(s); 
} 

public void writeBinaryFile(String fileName, String mimeType, String encoding) throws Exception { 
    String s = "--" + boundary + CRLF; 
    s += "Content-Type: " + mimeType + CRLF; 
    text.append(s); 

    java.nio.file.Path path = Paths.get(fileName); 
    byte[] data = Files.readAllBytes(path); 
    text.append(new String(data, encoding)).append(CRLF); 
} 

public void finish() { 
    text.append("--").append(boundary).append("--").append(CRLF); 
} 

private static void printResponse(URLConnection urlConnection) { 
    try { 
     InputStream is = urlConnection.getInputStream(); 
     while (is.available() != 0) { 
      byte[] data = new byte[is.available()]; 
      is.read(data); 
      System.out.println(new String (data, "UTF-8")); 
     } 
    } catch (Exception exc) { 
     exc.printStackTrace(); 
    } 
} 

public static void main(String[] args) throws Exception { 
    PhotoTest photoTest = new PhotoTest(); 
    photoTest.writeJson("ad9821e6-d308-472b-b21f-308b08c3fa70"); 
    //photoTest.writeBinaryFile("K:\\Downloads\\test.jpg", "image/jpeg", "UTF-8"); 
    photoTest.finish(); 
    System.out.println(photoTest.getText()); 

    URL url = new URL(MEDIA_ADD_PHOTO); 
    URLConnection urlConnection = url.openConnection(); 
    urlConnection.setDoOutput(true); 
    urlConnection.setUseCaches(false); 
    ((HttpURLConnection) urlConnection).setRequestMethod("POST"); 
    urlConnection.setRequestProperty("Accept-Charset", "UTF-8"); 
    urlConnection.setRequestProperty("Content-Type", "multipart/related; boundary=" + photoTest.getBoundary()); 
    urlConnection.setRequestProperty("Content-Length", Integer.toString(photoTest.getLength())); 
    OutputStream output = urlConnection.getOutputStream(); 
    output.write(photoTest.getContent().getBytes()); 
    output.flush(); 
    output.close(); 

    printResponse(urlConnection); 
} 

На данный момент, я удалил часть изображения (только чтобы проверить, могу ли я пройти мимо перехватчиков к своему собственному серверному коду, который должен проверить, присутствует ли изображение).Как вы можете видеть, что я напечатал сообщение, который встроен в консоль, это дает мне это:

--the_photo 
Content-Type: application/json 

{"objectToLinkTo":"ad9821e6-d308-472b-b21f-308b08c3fa70"} 

--the_photo-- 

Я еще получаю ту же ошибку. Может кто-нибудь объяснить мне, что я делаю неправильно?

+0

Разрыв строки по умолчанию в поля заголовка - CRLF = "\ r \ n". Итак, здесь также: http://www.w3.org/Protocols/rfc1341/7_2_Multipart.html#z0. –

+0

Я просто пробовал это, но это не помогло: я добавил 'private static final String CRLF =" \ r \ n ";', а затем всегда добавлял это ко всем строкам вместо "\ n". Все еще получаю ту же ошибку ... – testuser

+0

Я добавил свои изменения кода. Спасибо, что постарался мне помочь – testuser

ответ

1

Хорошо, так что, в конце концов, это была небольшая ошибка, как я думал.

Я случайно начал редактировать вещи - на самом деле я хотел попробовать отладить все это, но так как я никогда не достиг своего собственного кода на стороне сервера и застрял в слое Apache CXF, я не мог. Тогда я подумал: давайте просто прокомментировать перехватчик:

<jaxrs:server address="/v1/photos"> 
    <jaxrs:serviceBeans> 
     <ref bean="resourceV1" /> 
    </jaxrs:serviceBeans> 
    <!--<jaxrs:inInterceptors>--> 
     <!--<bean class="org.apache.cxf.interceptor.AttachmentInInterceptor"/>--> 
    <!--</jaxrs:inInterceptors>--> 
    <jaxrs:features> 
     <cxf:logging /> 
    </jaxrs:features> 
    <jaxrs:providers> 
     <bean class="commons.exceptions.exceptionwrapper.BusinessExceptionWrapper" /> 
     <bean class="commons.exceptions.exceptionwrapper.RuntimeExceptionWrapper" /> 
     <bean class="org.codehaus.jackson.jaxrs.JacksonJaxbJsonProvider" /> 
    </jaxrs:providers> 
</jaxrs:server> 

Волшебно: теперь он работает. Я не знаю, почему у меня был AttachmentInInterceptor.

Благодарим за помощь.