【问题标题】:Grizzly HTTP Server 415 Unsupported Media TypeGrizzly HTTP Server 415 不支持的媒体类型
【发布时间】:2016-06-08 13:54:54
【问题描述】:

我正在使用 RESTEasy 和 WildFly 9.0.2 开发一组 REST 服务。

其中一个允许我上传文件。

@POST
@Path("/upload")
@Consumes(MediaType.MULTIPART_FORM_DATA)
public Response upload(MultipartFormDataInput input);

我成功调用了 REST 服务并将文件上传到服务器,所以我开始实现集成测试。

为此,我使用的是嵌入式 Grizzly HTTP 服务器:

@Before
public void setUp() throws Exception {
    // Weld and container initialization
    weld = new Weld();
    weld.initialize();
    ResourceConfig resourceConfig = new ResourceConfig().packages("...");
    server = GrizzlyHttpServerFactory.createHttpServer(URI.create(BASE_URI), resourceConfig);
}

当我尝试测试新创建的服务时出现问题:

@Test
public void hubbleMapServiceUploadMapTest() throws FileNotFoundException, IOException {
    Client client = null;
    WebTarget webTarget = null;
    Builder builder = null;
    Response response = null;

    try {
        client = ClientBuilder.newBuilder().build();

        webTarget = client.target(BASE_URI).path("/service/upload");
        builder = webTarget.request(MediaType.APPLICATION_JSON, MediaType.TEXT_PLAIN, MediaType.WILDCARD);

        response = builder.post(Entity.entity(getEntityAsMultipart(), MediaType.MULTIPART_FORM_DATA));

    } catch (Exception ex) {
        ex.printStackTrace();
    } finally {
        if (response != null) {
            response.close();
        }

        if (client != null) {
            client.close();
        }
    }

    assertNotNull(response);
    assertThat(response.getStatus(), is(Status.OK.getStatusCode()));
}

private GenericEntity<MultipartFormDataOutput> getEntityAsMultipart() {
    String resource = "my.file";
    MultipartFormDataOutput mfdo = new MultipartFormDataOutput();

    try {
        mfdo.addFormData("file",
                new FileInputStream(new File(getClass().getClassLoader().getResource(resource).getFile())),
                MediaType.APPLICATION_OCTET_STREAM_TYPE, resource);
    } catch (FileNotFoundException e) {
        e.printStackTrace();
    }

    GenericEntity<MultipartFormDataOutput> entity = new GenericEntity<MultipartFormDataOutput>(mfdo) {
    };

    return entity;
}

响应代码始终是415 Unsupported Media Type

所有剩余的集成测试都正常工作。

我做错了什么?我是否需要以某种方式启用 Grizzly 的 Multipart 功能?

【问题讨论】:

  • 您需要在 Jersey 注册 multipart 提供者。如果您只使用 Jersey 进行测试,那么使用 RESTEasy 可能会更好。在一种实现中可能存在差异,而在另一种中则不行。您应该查看embedded containers 的文档以查看 RESTEasy 在独立模式下运行的示例。使用 RESTEasy,您无需注册提供程序
  • 这是一个使用 Jdk HttpServer 的complete example。唯一的问题是它不支持像 HttpServletRequest 这样的 servlet API,如果您正在使用的话。为此,您最好使用 Undertow 容器。上一条评论的链接中有一个示例。我认为this dependency 是您唯一需要的。
  • @peeskillet,非常感谢您的意见!是否有任何提到的嵌入式容器允许与 CDI 集成?对于 Grizzly,为了启用 CDI,我使用 jersey-weld2-se 并显式初始化 weld。我可以对上述任何容器做同样的事情吗?
  • 是的,这是我一直在看的一件事,我不太确定我不确定集成 CDI 有多么容易,因为我从来没有做过。你可以看看resteasy-cdi。如果您查看测试,您会看到正在使用它的示例。另一种选择是使用 Arquillian,它可以运行完整的 EE 环境。但这是一个更复杂的测试框架,需要学习。
  • 如果您想坚持使用 Jersey,您可能需要查看 this。这是自动向 RESTEasy 注册以获得多部分支持的所有提供程序的列表。您是否需要全部注册,以及他们是否都将在泽西岛工作,我不确定。但是您可以尝试注册它们

标签: jax-rs resteasy http-status-code-415


【解决方案1】:

在听从@peeskillet的建议后,我切换到Sun JDK HTTP Server具有CDI意识的嵌入式服务器。

要实现这一点,需要执行以下操作:

  1. 添加 RESTEasy 和 WELD 必要的 Maven 依赖项:

    <dependency>
        <groupId>org.jboss.resteasy</groupId>
        <artifactId>resteasy-jdk-http</artifactId>
        <version>3.0.17.Final</version>
        <scope>test</scope>
    </dependency>
    
    <dependency>
        <groupId>org.jboss.resteasy</groupId>
        <artifactId>resteasy-cdi</artifactId>
        <version>3.0.17.Final</version>
        <scope>test</scope>
    </dependency>
    
    <dependency>
        <groupId>org.jboss.weld.se</groupId>
        <artifactId>weld-se</artifactId>
        <version>2.3.4.Final</version>
        <scope>test</scope>
    </dependency>
    
  2. 配置 WELD 和 RESTEasy CDI 扩展以用于 Sun JDK HTTP Server 的部署配置:

    private Weld weld;
    private SunHttpJaxrsServer server;
    
    @Before
    public void setUp() throws Exception {
        // Weld initialization
        weld = new Weld();
        weld.initialize();
    
        // RESTEasy CDI extension configuration
        ResteasyCdiExtension cdiExtension = CDI.current().select(ResteasyCdiExtension.class).get();
        ResteasyDeployment deployment = new ResteasyDeployment();
        deployment.setActualResourceClasses(cdiExtension.getResources());
        deployment.setInjectorFactoryClass(CdiInjectorFactory.class.getName());
        deployment.getActualProviderClasses().addAll(cdiExtension.getProviders());
    
        // Container initialization
        server = new SunHttpJaxrsServer();
        server.setDeployment(deployment);
        server.setPort(8787);
        server.setRootResourcePath("/some-context-root/rest");
        server.getDeployment().getActualResourceClasses().add(MyService.class);
        server.start();
    }
    

为了了解如何配置 RESTEasy 的 CDI 扩展,我依赖于 @John AmentNettyTest 示例。

【讨论】:

    猜你喜欢
    • 2017-07-05
    • 2015-08-29
    • 2013-01-16
    • 1970-01-01
    • 2013-01-22
    • 1970-01-01
    • 2014-05-10
    相关资源
    最近更新 更多