org.glassfish.jersey.server.ContainerException:java.io.IOException:流关闭 [英] org.glassfish.jersey.server.ContainerException: java.io.IOException: Stream closed

查看:301
本文介绍了org.glassfish.jersey.server.ContainerException:java.io.IOException:流关闭的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在扩展JAX-RS应用程序的应用程序类中注册了两个ContainerRequestFilter过滤器和一个ContainerResponseFilter:

I have register two ContainerRequestFilter filters and one ContainerResponseFilter in my application class that extends a JAX-RS Application:

过滤为:

register(LoggingResponseFilter.class);
register(AuthorizationRequestFilter.class);
register(LikeRequestFilter.class);

,当我尝试调用目标方法资源时,出现异常.

and when I tries to call a targeted method resource I have an Exception.

资源方法为:

@Override
@POST
@Path("/{userId}/like")
@TokenResource
@GMTResource   // to validate GMT of client and server
@Like       // for like filter
public Response like(@HeaderParam("token") @NotNull String token,
            @HeaderParam("user-agent") String userAgent,
            @NotNull @Valid UserFriendsBaseModel userFriendsBaseModel)
            throws BadRequestException, UnauthorizedException,
            ForbiddenException, InternalServerError {
    userService.like(userFriendsBaseModel,userAgent);
    return Response.ok().build();
}

例外:

    javax.servlet.ServletException: org.glassfish.jersey.server.ContainerException: java.io.IOException: Stream closed
    org.glassfish.jersey.servlet.WebComponent.service(WebComponent.java:419)
    org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:381)
    org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:344)
    org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:221)
    org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
root cause

org.glassfish.jersey.server.ContainerException: java.io.IOException: Stream closed
    org.glassfish.jersey.servlet.internal.ResponseWriter.rethrow(ResponseWriter.java:256)
    org.glassfish.jersey.servlet.internal.ResponseWriter.failure(ResponseWriter.java:238)
    org.glassfish.jersey.server.ServerRuntime$Responder.process(ServerRuntime.java:480)
    org.glassfish.jersey.server.ServerRuntime$2.run(ServerRuntime.java:311)
    org.glassfish.jersey.internal.Errors$1.call(Errors.java:271)
    org.glassfish.jersey.internal.Errors$1.call(Errors.java:267)
    org.glassfish.jersey.internal.Errors.process(Errors.java:315)
    org.glassfish.jersey.internal.Errors.process(Errors.java:297)
    org.glassfish.jersey.internal.Errors.process(Errors.java:267)
    org.glassfish.jersey.process.internal.RequestScope.runInScope(RequestScope.java:317)
    org.glassfish.jersey.server.ServerRuntime.process(ServerRuntime.java:286)
    org.glassfish.jersey.server.ApplicationHandler.handle(ApplicationHandler.java:1072)
    org.glassfish.jersey.servlet.WebComponent.service(WebComponent.java:399)
    org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:381)
    org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:344)
    org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:221)
    org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
root cause

java.io.IOException: Stream closed
    org.apache.catalina.connector.InputBuffer.read(InputBuffer.java:312)
    org.apache.catalina.connector.CoyoteInputStream.read(CoyoteInputStream.java:200)
    org.glassfish.jersey.message.internal.EntityInputStream.read(EntityInputStream.java:101)
    org.glassfish.jersey.message.internal.ReaderInterceptorExecutor$UnCloseableInputStream.read(ReaderInterceptorExecutor.java:301)
    com.fasterxml.jackson.core.json.ByteSourceJsonBootstrapper.ensureLoaded(ByteSourceJsonBootstrapper.java:503)
    com.fasterxml.jackson.core.json.ByteSourceJsonBootstrapper.detectEncoding(ByteSourceJsonBootstrapper.java:129)
    com.fasterxml.jackson.core.json.ByteSourceJsonBootstrapper.constructParser(ByteSourceJsonBootstrapper.java:224)
    com.fasterxml.jackson.core.JsonFactory._createParser(JsonFactory.java:1242)
    com.fasterxml.jackson.core.JsonFactory.createParser(JsonFactory.java:753)
    com.fasterxml.jackson.jaxrs.base.ProviderBase._createParser(ProviderBase.java:791)
    com.fasterxml.jackson.jaxrs.base.ProviderBase.readFrom(ProviderBase.java:760)
    org.glassfish.jersey.message.internal.ReaderInterceptorExecutor$TerminalReaderInterceptor.invokeReadFrom(ReaderInterceptorExecutor.java:259)
    org.glassfish.jersey.message.internal.ReaderInterceptorExecutor$TerminalReaderInterceptor.aroundReadFrom(ReaderInterceptorExecutor.java:235)
    org.glassfish.jersey.message.internal.ReaderInterceptorExecutor.proceed(ReaderInterceptorExecutor.java:155)
    org.glassfish.jersey.server.internal.MappableExceptionWrapperInterceptor.aroundReadFrom(MappableExceptionWrapperInterceptor.java:74)
    org.glassfish.jersey.message.internal.ReaderInterceptorExecutor.proceed(ReaderInterceptorExecutor.java:155)
    org.glassfish.jersey.message.internal.MessageBodyFactory.readFrom(MessageBodyFactory.java:1075)
    org.glassfish.jersey.message.internal.InboundMessageContext.readEntity(InboundMessageContext.java:853)
    org.glassfish.jersey.server.ContainerRequest.readEntity(ContainerRequest.java:270)
    org.glassfish.jersey.server.internal.inject.EntityParamValueFactoryProvider$EntityValueFactory.provide(EntityParamValueFactoryProvider.java:96)
    org.glassfish.jersey.server.spi.internal.ParameterValueHelper.getParameterValues(ParameterValueHelper.java:81)
    org.glassfish.jersey.server.model.internal.JavaResourceMethodDispatcherProvider$AbstractMethodParamInvoker.getParamValues(JavaResourceMethodDispatcherProvider.java:125)
    org.glassfish.jersey.server.model.internal.JavaResourceMethodDispatcherProvider$ResponseOutInvoker.doDispatch(JavaResourceMethodDispatcherProvider.java:158)
    org.glassfish.jersey.server.model.internal.AbstractJavaResourceMethodDispatcher.dispatch(AbstractJavaResourceMethodDispatcher.java:97)
    org.glassfish.jersey.server.model.ResourceMethodInvoker.invoke(ResourceMethodInvoker.java:389)
    org.glassfish.jersey.server.model.ResourceMethodInvoker.apply(ResourceMethodInvoker.java:347)
    org.glassfish.jersey.server.model.ResourceMethodInvoker.apply(ResourceMethodInvoker.java:102)
    org.glassfish.jersey.server.ServerRuntime$2.run(ServerRuntime.java:303)
    org.glassfish.jersey.internal.Errors$1.call(Errors.java:271)
    org.glassfish.jersey.internal.Errors$1.call(Errors.java:267)
    org.glassfish.jersey.internal.Errors.process(Errors.java:315)
    org.glassfish.jersey.internal.Errors.process(Errors.java:297)
    org.glassfish.jersey.internal.Errors.process(Errors.java:267)
    org.glassfish.jersey.process.internal.RequestScope.runInScope(RequestScope.java:317)
    org.glassfish.jersey.server.ServerRuntime.process(ServerRuntime.java:286)
    org.glassfish.jersey.server.ApplicationHandler.handle(ApplicationHandler.java:1072)
    org.glassfish.jersey.servlet.WebComponent.service(WebComponent.java:399)
    org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:381)
    org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:344)
    org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:221)
    org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)

我还将请求过滤器的优先级设置为:

I have also set the priority for request filters as:

@Priority(200)
public class LikeRequestFilter implements ContainerRequestFilter {

    private final Logger _logger = LoggerFactory.getLogger(LikeRequestFilter.class);

    @Inject
    ResourceInfo resourceInfo;

    @Inject
    UriInfo uriInfo;

    @Autowired
    UserManager userManager;

    @Override
    public void filter(ContainerRequestContext requestContext) throws IOException {
        if (resourceInfo.getResourceMethod().isAnnotationPresent(Like.class)) {
            try {
                ObjectMapper jsonMapper = new ObjectMapper();
                final UserFriendsBaseModel usm = jsonMapper
                        .readValue(requestContext.getEntityStream(), UserFriendsBaseModel.class);
                boolean isLiked = userManager.isLiked(usm);
                /**
                 *  If already liked (on api server db ) the check for other conditions
                 *  otherwise consider as first time like request and send to resource for processing 
                 */
                if(isLiked) {
                    /**
                     * Check if already liked on openfire
                     */
                    boolean isRoster = userManager.isRoster(usm);
                    /**
                     * if already roster then check for reverse like
                     * else add entry in add roster failure request
                     */
                    if(isRoster) {
                        /**
                         * Check if reverse like on api server if liked then check for openfire
                         */
                        final UserFriendsBaseModel reverseModel = UserFriendsBaseModel.reverse(usm);
                        boolean isReverseLiked = userManager.isLiked(reverseModel);
                        /**
                         * Reverse liked(Friends) on api server db . Check on openfire
                         */
                        if(isReverseLiked) {
                            boolean isReverseRoster = userManager.isRosterFriend(reverseModel);
                            /**
                             * If friend on openfire then send push to both user for new Match
                             */
                            if(isReverseRoster) {
                                // TODO send push
                            } else {
                                userManager.addRosterFailureRequest(reverseModel);
                            }
                        }

                    } else {
                        userManager.addRosterFailureRequest(usm);
                    }

                    requestContext.abortWith(Response.ok().build());
                }


            } catch (Exception e) {
                _logger.error("Something went wrong in Like request Filter", e);
            }

            _logger.info("end of if in LIKE Filter : ");
        }
        _logger.info("End of LIKE Filter : ");
    }

}

,对于AuthorizationRequestFilter过滤器,则为:

@Priority(100)
public class AuthorizationRequestFilter implements ContainerRequestFilter {

    private final Logger _logger = LoggerFactory
            .getLogger(AuthorizationRequestFilter.class);

    @Inject
    ResourceInfo resourceInfo;

    @Inject
    UriInfo uriInfo;

    @Autowired
    AuthorizationService authorizationService;

,响应过滤器为:

public class LoggingResponseFilter implements ContainerResponseFilter {

    final static Logger _logger = Logger.getLogger(LoggingResponseFilter.class
            .getName());

    public void filter(ContainerRequestContext requestContext,ContainerResponseContext responseContext) throws IOException {
        String method = requestContext.getMethod();

        _logger.info("Requesting : " + method + " for path " + requestContext.getUriInfo().getPath());

然后在AuthorizationRequestFilter之后在过滤器链中调用时LikeRequestFilter中会出现问题.

then problem occurs in LikeRequestFilter when it calls in filter chain after AuthorizationRequestFilter.

我无法找出问题所在?如何将请求过滤器与响应过滤器链接在一起?

I am unable to find out what's going wrong ? how to chain request filter with response filter ?

推荐答案

问题出在LikeRequestFilter上.您正在使用ObjectMapper读取请求实体InputStream.通常,InputStream只能读取一次,然后它们为空.因此,ObjectMapper读取流后,将其关闭.因此,当Jersey尝试读取它时,由于已关闭,它无法读取.即使它没有关闭,它仍然是空的.

The problem is with the LikeRequestFilter. You are reading the request entity InputStream with the ObjectMapper. Generally, InputStreams can only be read once, then they are empty. For this reason, after the ObjectMapper reads the stream, it closes it. So when Jersey tries to read it, it can't, as it's closed. Even if it wasn't closed, it would still be empty.

对于此用例,Jersey允许我们缓冲流,因此可以多次读取它.不过,您需要执行的操作是将ContainerRequestContext强制转换为具有bufferEntity()方法的ContainerRequest.它还具有帮助读取流的方法,例如readEntity,其用法类似于客户端Response#readEntity().

For this use case, Jersey allows us to buffer the stream, so it can be read multiple times. What you need to do though is cast the ContainerRequestContext to ContainerRequest, which has a bufferEntity() method. It also has methods to help with the reading of the stream, like readEntity, that is used similar to the client Response#readEntity().

所以您可以做类似的事情

So you could do something like

@Override
public void filter(ContainerRequestContext requestContext) throws IOException {
    try {
        ContainerRequest cr = (ContainerRequest) requestContext;
        cr.bufferEntity();
        final UserFriendsBaseModel bm = cr.readEntity(UserFriendsBaseModel.class);

这篇关于org.glassfish.jersey.server.ContainerException:java.io.IOException:流关闭的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆