eclipse-ee4j / jersey

Eclipse Jersey Project - Read our Wiki:
https://github.com/eclipse-ee4j/jersey/wiki
Other
692 stars 355 forks source link

Jersey 2.8 and JSONP with missing closing parenthese for JsonStructure #2805

Closed jerseyrobot closed 10 years ago

jerseyrobot commented 10 years ago

I'm using Jersey 2.8 to generate JSONP with JsonStructur (super type for the two structured types in JSON JsonObject and JsonArray) as return type. Unfortunately the generated JSONP is syntactically incorrect as the closing parenthese is missing, e.g.

callback(
{
    "madeByAdmin":false,
    "linesChanged":1,
    "logMessage":"fixing typo"
}

is returned. I've modified and tested the example given by Jersey (see examples/json-processing-webapp) and it the JUnit test fails with the following exception:

Schwerwiegend: An I/O error has occurred while writing a response message entity to the container output stream.
org.glassfish.jersey.server.internal.process.MappableException: java.io.IOException: stream closed
    at org.glassfish.jersey.server.internal.MappableExceptionWrapperInterceptor.aroundWriteTo(MappableExceptionWrapperInterceptor.java:96)
    at org.glassfish.jersey.message.internal.WriterInterceptorExecutor.proceed(WriterInterceptorExecutor.java:162)
    at org.glassfish.jersey.message.internal.MessageBodyFactory.writeTo(MessageBodyFactory.java:1154)
    at org.glassfish.jersey.server.ServerRuntime$Responder.writeResponse(ServerRuntime.java:613)
    at org.glassfish.jersey.server.ServerRuntime$Responder.processResponse(ServerRuntime.java:375)
    at org.glassfish.jersey.server.ServerRuntime$Responder.process(ServerRuntime.java:365)
    at org.glassfish.jersey.server.ServerRuntime$1.run(ServerRuntime.java:272)
    at org.glassfish.jersey.internal.Errors$1.call(Errors.java:271)
    at org.glassfish.jersey.internal.Errors$1.call(Errors.java:267)
    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:267)
    at org.glassfish.jersey.process.internal.RequestScope.runInScope(RequestScope.java:297)
    at org.glassfish.jersey.server.ServerRuntime.process(ServerRuntime.java:252)
    at org.glassfish.jersey.server.ApplicationHandler.handle(ApplicationHandler.java:1023)
    at org.glassfish.jersey.jdkhttp.JdkHttpHandlerContainer.handle(JdkHttpHandlerContainer.java:165)
    at com.sun.net.httpserver.Filter$Chain.doFilter(Unknown Source)
    at sun.net.httpserver.AuthFilter.doFilter(Unknown Source)
    at com.sun.net.httpserver.Filter$Chain.doFilter(Unknown Source)
    at sun.net.httpserver.ServerImpl$Exchange$LinkHandler.handle(Unknown Source)
    at com.sun.net.httpserver.Filter$Chain.doFilter(Unknown Source)
    at sun.net.httpserver.ServerImpl$Exchange.run(Unknown Source)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
    at java.lang.Thread.run(Unknown Source)
Caused by: java.io.IOException: stream closed
    at sun.net.httpserver.FixedLengthOutputStream.write(Unknown Source)
    at sun.net.httpserver.PlaceholderOutputStream.write(Unknown Source)
    at org.glassfish.jersey.message.internal.CommittingOutputStream.write(CommittingOutputStream.java:244)
    at org.glassfish.jersey.server.internal.JsonWithPaddingInterceptor.aroundWriteTo(JsonWithPaddingInterceptor.java:106)
    at org.glassfish.jersey.message.internal.WriterInterceptorExecutor.proceed(WriterInterceptorExecutor.java:162)
    at org.glassfish.jersey.server.internal.MappableExceptionWrapperInterceptor.aroundWriteTo(MappableExceptionWrapperInterceptor.java:88)
    ... 24 more

It seems, that the used JsonStructureBodyWriter closes the Outputstream and the JsonWithPaddingInterceptor is not able to write the closing parenthese to the commiting OutputStream. To test this by yourself you can modify the ChangeListResource class from the mentioned example with this additional method:

/**
 * @param callback
 * @param type
 */
@GET
@Path( "latestJson" )
@JSONP( queryParam = JSONP.DEFAULT_QUERY )
public JsonObject getLastChangeAsJsonObject( @QueryParam( JSONP.DEFAULT_QUERY ) String callback, @QueryParam( "type" ) int type )
{
    return toJsonObject( changes.get( changes.size() - 1 ) );
}

private JsonObject toJsonObject( final ChangeRecordBean bean )
{
    if( bean != null )
    {
        return Json.createObjectBuilder().add( "madeByAdmin", bean.madeByAdmin ).add( "linesChanged", bean.linesChanged ).add( "logMessage", bean.logMessage ).build();
    }
    return null;
}

And the JsonWithPaddingTest class with this test method:

@Test
public void testGetOnLatestJsonJavascriptFormat()
{
    WebTarget target = target(ShoppingAPIApplication.CHANGES_PATH);
    String js = target.path("latestJson").request("application/x-javascript").get(String.class);
    assertTrue(js.startsWith("callback"));
    assertTrue(js.endsWith(")"));
}

Environment

Linux, Windows, Apache, Tomcat 7

Affected Versions

[2.8]

jerseyrobot commented 6 years ago
jerseyrobot commented 10 years ago

@glassfishrobot Commented Reported by forchel

jerseyrobot commented 10 years ago

@glassfishrobot Commented mfuksa said: Hi, thank you for the bug report. I am moving the issue to the backlog.

Mira

proposal for fix: simple fix could be to wrap the outputStream in JsonStructureBodyWriter and do not propagate the close method. Another option is to pass already wrapper output stream to MBWs so that no MBW can close the stream. The second option looks better for me.

jerseyrobot commented 10 years ago

@glassfishrobot Commented Was assigned to michalgajdos

jerseyrobot commented 7 years ago

@glassfishrobot Commented This issue was imported from java.net JIRA JERSEY-2533

jerseyrobot commented 10 years ago

@glassfishrobot Commented Marked as fixed on Friday, June 27th 2014, 5:24:38 am