Jax-ws Jersey 表单数据上传响应返回 500 错误

Jax-ws Jersey formdata upload response returning 500 error

问候 Whosebug 成员。

背景资料: 这是一个基于 spring-boot 的项目,它使用 JAX-RS / Jersey 作为其 rest HTTP 服务器而不是 spring rest。

错误解释及问题:

将文件从一台服务器发送到另一台服务器并收到响应。 (简单吧?)下面的代码在功能上是有效的。但发件人收到的不是 200 响应,而是 500 内部服务器错误以及以下堆栈跟踪。

java.lang.IllegalStateException: No such MIME Part: Part=0:binary
at org.jvnet.mimepull.DataHead.read(DataHead.java:115)
at org.jvnet.mimepull.MIMEPart.read(MIMEPart.java:69)
at org.glassfish.jersey.media.multipart.BodyPartEntity.getInputStream(BodyPartEntity.java:65)
at org.glassfish.jersey.media.multipart.internal.FormDataParamValueParamProvider$FormDataParamValueProvider.apply(FormDataParamValueParamProvider.java:263)
at org.glassfish.jersey.media.multipart.internal.FormDataParamValueParamProvider$FormDataParamValueProvider.apply(FormDataParamValueParamProvider.java:222)
at org.glassfish.jersey.server.spi.internal.ParamValueFactoryWithSource.apply(ParamValueFactoryWithSource.java:50)
at org.glassfish.jersey.server.spi.internal.ParameterValueHelper.getParameterValues(ParameterValueHelper.java:64)
at org.glassfish.jersey.server.model.internal.JavaResourceMethodDispatcherProvider$AbstractMethodParamInvoker.getParamValues(JavaResourceMethodDispatcherProvider.java:109)
at org.glassfish.jersey.server.model.internal.JavaResourceMethodDispatcherProvider$ResponseOutInvoker.doDispatch(JavaResourceMethodDispatcherProvider.java:176)
at org.glassfish.jersey.server.model.internal.AbstractJavaResourceMethodDispatcher.dispatch(AbstractJavaResourceMethodDispatcher.java:79)
at org.glassfish.jersey.server.model.ResourceMethodInvoker.invoke(ResourceMethodInvoker.java:469)

调试后我注意到接收服务器@FormDataParam 包含在 Response.ok() 对象中。

如果我定义Response.ok(),这是我不明白的部分。为什么它包含请求参数?根据发送响应的类型,文件已被使用。

下图是debug进入Response时拍的

配置: 球衣设置

@Configuration

@ApplicationPath("/idoc") public class JerseyConfiguration 扩展 ResourceConfig {

private static final Logger logger = LoggerFactory.getLogger(JerseyConfiguration.class);

public JerseyConfiguration() {
    packages("ctx.cf.arcus.controllers");
    register(MultiPartFeature.class);
    register(CORSResponseFilter.class);
    register(JacksonProvider.class);
    register(DebugExceptionMapper.class);

    HashMap<String, Object> properties = new HashMap<String, Object>();
    properties.put("jersey.config.server.response.setStatusOverSendError", true);

    setProperties(properties);

}

}

发送服务器我配置了以下代码:

Client client = ClientBuilder.newClient(new ClientConfig().register(MultiPartFeature.class));

    WebTarget webTarget = client.target(url);
    FormDataMultiPart part = new FormDataMultiPart();

    final FormDataBodyPart p1 = new StreamDataBodyPart("file", this.document.getStream());
    part.bodyPart(p1);
    final FormDataBodyPart p2 = new FormDataBodyPart("size", String.valueOf(this.document.getSize()));
    part.bodyPart(p2);
    Response response = null;
    try {
        response = webTarget.request().header("Authorization", "Bearer " + token)
                .post(Entity.entity(part, MediaType.MULTIPART_FORM_DATA), Response.class);

    } catch (Exception e) {
        response = Response.serverError().build();
    }

接收服务器

@POST
@Path("/idoc")
public Response idocPassThroughTranslation(@FormDataParam("file") InputStream uploadedInputStream,
        @FormDataParam("size") long size, @Context HttpServletRequest request)
        throws IOException, ServletException, FormatException {

    <Logic omitted>

    return Response.ok().build();
}

好的。我花了一天时间来尝试解决这个问题。但无法找到此行为的根本原因。

所以我选择了一个变通解决方案。

我使用 jersey exception mapper 检查抛出的特定期望和方法,因为它应该只应用于代码的那个位置和响应状态,以查看是否需要用 200 ok 覆盖或传递500.

@Provider
public class RouterResponseExceptionMapper implements 
ExceptionMapper<IllegalStateException> {

@Context
private HttpServletResponse response;

@Context
private ResourceInfo resourceInfo;

@Override
public Response toResponse(IllegalStateException exception) {
    
    if (this.resourceInfo.getResourceMethod().getName().equals("PassThrough")
            && this.response.getStatus() == 200) {
        return Response.ok().build();
    } else {
        return Response.serverError().entity(Throwables.getStackTraceAsString(exception)).build();
    }
}

}