6

Sto cercando di creare un test per un metodo POST in una classe di risorse in un programma di Jersey.MessageBodyWriter non trovato per il tipo di supporto = multipart/form-data in JerseyTest

Ecco il metodo della risorsa POST:

@POST @Path("/new") 
@Consumes(MediaType.MULTIPART_FORM_DATA) 
public Response HTTPPostMethod(@FormDataParam("file") InputStream fileIS, 
          @FormDataParam("file") FormDataContentDisposition contentDispositionHeader) { 
    // ... some code that handles the InputStream 
} 

mio ResourceConfig viene creato nel seguente modo:

public class MyApp extends ResourceConfig { 

    public MyApp(String param) { 
     register(createMoxyJsonResolver());  
     register(MultiPartFeature.class); 
     register(MyResource.class); 
    } 

    private static ContextResolver<MoxyJsonConfig> createMoxyJsonResolver() { 
     final MoxyJsonConfig moxyJsonConfig = new MoxyJsonConfig(); 
     Map<String, String> nsPrefixManager = new HashMap<String, String>(1); 
     nsPrefixManager.put("http://www.w3.org/2001/XMLSchema-instance", "xsi"); 
     moxyJsonConfig.setNamespacePrefixMapper(nsPrefixManager).setNamespaceSeparator(':'); 
     return moxyJsonConfig.resolver(); 
    } 

    /** 
    * Start the Grizzly HTTP Server 
    * 
    */ 
    public final void startHttpServer(int port) { 
     try { 
      final String url = "http://localhost:" + port + "/myapp"; 
      final HttpServer server = 
        GrizzlyHttpServerFactory 
         .createHttpServer(URI.create(url), this); 

      Runtime.getRuntime().addShutdownHook(new Thread(new Runnable() { 
       public void run() { 
        server.shutdown(); 
       } 
      })); 
      Thread.currentThread().join(); 

     } catch (InterruptedException e) { 
      e.printStackTrace(); 
     } 
    } 

    public static void main(String[] args) { 
     try { 
      final MyApp app = new MyApp(args[1]); 
      int port = Integer.parseInt(args[0]); 
      app.startHttpServer(port); 
     } catch(NumberFormatException e) { 
      e.printStackTrace(); 
     } 
    } 
} 

mia messa a punto di test in jersey:

public class TestBase extends JerseyTest { 

    protected Application app; 
    protected static final String param = "myparam"; 

    @Override 
    protected Application configure() { 
     // The MultiPartFeature is registered. 
     this.app = new MyApp(param); 
     return app; 
    } 
} 

Infine, il prova che sta causando problemi:

public class MyResourceTest extends TestBase { 

// ... 

    @Test 
    public void testHTTPPost() { 

     try { 

      FileDataBodyPart filePart = new FileDataBodyPart("file", new File("path/to/a/file/i/know/exists")); 
      FormDataMultiPart formDataMultipart = new FormDataMultiPart(); 
      FormDataMultiPart multipart = (FormDataMultiPart)formDataMultipart.bodyPart(filePart); 

      Response result = target("/myResource/new").request().post(Entity.entity(multipart, multipart.getMediaType())); 
      formDataMultipart.close(); 
      multipart.close(); 

      assertEquals(Response.Status.OK.getStatusCode(), result.getStatus()); 
     } catch (IOException e) { 
      e.printStackTrace(); 
     } 
    } 

// ... 

} 

che sto ottenendo sempre l'errore:

org.glassfish.jersey.message.internal.MessageBodyProviderNotFoundException: MessageBodyWriter not found for media type=multipart/form-data, type=class org.glassfish.jersey.media.multipart.FormDataMultiPart, genericType=class org.glassfish.jersey.media.multipart.FormDataMultiPart. 
    at org.glassfish.jersey.message.internal.WriterInterceptorExecutor$TerminalWriterInterceptor.aroundWriteTo(WriterInterceptorExecutor.java:247) 
    at org.glassfish.jersey.message.internal.WriterInterceptorExecutor.proceed(WriterInterceptorExecutor.java:162) 
    at org.glassfish.jersey.message.internal.MessageBodyFactory.writeTo(MessageBodyFactory.java:1130) 
    at org.glassfish.jersey.client.ClientRequest.writeEntity(ClientRequest.java:502) 
    at org.glassfish.jersey.client.internal.HttpUrlConnector._apply(HttpUrlConnector.java:388) 
    at org.glassfish.jersey.client.internal.HttpUrlConnector.apply(HttpUrlConnector.java:285) 
    at org.glassfish.jersey.client.ClientRuntime.invoke(ClientRuntime.java:255) 
    at org.glassfish.jersey.client.JerseyInvocation$1.call(JerseyInvocation.java:684) 
    at org.glassfish.jersey.client.JerseyInvocation$1.call(JerseyInvocation.java:681) 
    at org.glassfish.jersey.internal.Errors.process(Errors.java:315) 
    at org.glassfish.jersey.internal.Errors.process(Errors.java:297) 
    at org.glassfish.jersey.internal.Errors.process(Errors.java:228) 
    at org.glassfish.jersey.process.internal.RequestScope.runInScope(RequestScope.java:444) 
    at org.glassfish.jersey.client.JerseyInvocation.invoke(JerseyInvocation.java:681) 
    at org.glassfish.jersey.client.JerseyInvocation$Builder.method(JerseyInvocation.java:437) 
    at org.glassfish.jersey.client.JerseyInvocation$Builder.post(JerseyInvocation.java:343) 
    at services.MyResourceTest.testHTTPPost(MyResourceTest.java:151) 
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) 
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) 
    at java.lang.reflect.Method.invoke(Method.java:497) 
    at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50) 
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12) 
    at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47) 
    at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17) 
    at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26) 
    at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:27) 
    at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325) 
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78) 
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57) 
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290) 
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71) 
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288) 
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58) 
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268) 
    at org.junit.runners.ParentRunner.run(ParentRunner.java:363) 
    at org.apache.maven.surefire.junit4.JUnit4Provider.execute(JUnit4Provider.java:252) 
    at org.apache.maven.surefire.junit4.JUnit4Provider.executeTestSet(JUnit4Provider.java:141) 
    at org.apache.maven.surefire.junit4.JUnit4Provider.invoke(JUnit4Provider.java:112) 
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) 
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) 
    at java.lang.reflect.Method.invoke(Method.java:497) 
    at org.apache.maven.surefire.util.ReflectionUtils.invokeMethodWithArray(ReflectionUtils.java:189) 
    at org.apache.maven.surefire.booter.ProviderFactory$ProviderProxy.invoke(ProviderFactory.java:165) 
    at org.apache.maven.surefire.booter.ProviderFactory.invokeProvider(ProviderFactory.java:85) 
    at org.apache.maven.surefire.booter.ForkedBooter.runSuitesInProcess(ForkedBooter.java:115) 
    at org.apache.maven.surefire.booter.ForkedBooter.main(ForkedBooter.java:75) 

ho provato il seguente codice nella TestBase, ma non ha funzionato:

@Override 
    protected Application configure() { 
     ResourceConfig app = new ResourceConfig(); 
     app.register(MultiPartFeature.class); 
     app.register(MyResource.class); 
     this.app = app; 
     return app; 
    } 

stesso errore. Cosa sto facendo di sbagliato qui?

+0

Questo è simile a https: // StackOverflow. it/questions/19668426/how-to-resolve-messagebodywriter-not-found-for-media-type-multipart-form-data-erer –

risposta

6

Il MultiPartFeature registra il numero MessageBodyWriter/MessageBodyReader necessario per gestire multipart. L'hai registrato sul server (che utilizzerà il lettore per deserializzare l'entità di richiesta in entrata), ma devi anche registrarlo sul client (che utilizza il writer per serializzare l'entità di richiesta in uscita).

In realtà ci sono alcuni posti in cui è possibile registrarlo. Un paio sono con lo WebTarget o con lo Client. Se si desidera registrare con il cliente, è possibile ignorare configureClient(ClientConfig) nel JerseyTest

@Override 
public void configureClient(ClientConfig config) { 
    config.register(MultiPartFeature.class); 
} 

Oppure, con l'WebTarget, si può semplicemente fare

target(...).register(MultiPartFeature.class).. 
+0

Grazie! Accettazione in un minuto. Ha fatto il metodo 'configureClient' e ha funzionato. – luispcosta