eclipse-ee4j / eclipse-ee4j/jersey
JsonProcessingFeature fails on single byte POST
- Dominant language
- Java
- Stars
- 730
- Forks
- 382
- PR merge metrics
- No merged PRs in 30d
Description
When attempting to POST a single digit JsonNumber as the contents of the body using the JsonProcessingFeature, the parse fails with an exception from javax.json of not enough characters to detect the input encoding.
While this is probably a bug with `org.glassfish.json.UnicodeDetectingInputStream` from the JSON-P project, trying to avoid this with using `application/json; charset=utf-8` as the Content-Type doesn't skip the encoding detection.
Eg:
```
curl -X POST -H "Content-Type: application/json" -d "1" http://localhost:9998/Eg
```
and
```
curl -X POST -H "Content-Type: application/json; charset=utf-8" -d "1" http://localhost:9998/Eg
```
both fail.
```java
package eg;
import java.net.URI;
import java.util.logging.ConsoleHandler;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.json.JsonValue;
import javax.ws.rs.Consumes;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.core.UriBuilder;
import org.glassfish.grizzly.http.server.HttpServer;
import org.glassfish.jersey.grizzly2.httpserver.GrizzlyHttpServerFactory;
import org.glassfish.jersey.jsonp.JsonProcessingFeature;
import org.glassfish.jersey.server.ResourceConfig;
@Path("Eg")
public class Eg {
@POST
@Consumes("application/json")
public void getHello(JsonValue val) {
System.out.println(val);
}
public static void main(String[] args) throws Exception {
makeGrizzlyLog();
URI baseUri = UriBuilder.fromUri("http://localhost/").port(9998).build();
ResourceConfig cfg = new ResourceConfig().register(Eg.class)
.register(JsonProcessingFeature.class);
HttpServer server = GrizzlyHttpServerFactory.createHttpServer(baseUri, cfg);
Runtime.getRuntime()
.addShutdownHook(new Thread(() -> {
server.shutdownNow();
}));
server.start();
Thread.currentThread().join();
}
private static void makeGrizzlyLog() {
Logger log = Logger.getLogger("org.glassfish.grizzly.http.server.HttpHandler");
log.setLevel(Level.FINE);
log.setUseParentHandlers(false);
ConsoleHandler ch = new ConsoleHandler();
ch.setLevel(Level.ALL);
log.addHandler(ch);
}
}
```
Stack trace the same with both `curl` invocations.
```
FINE: service exception
javax.json.JsonException: Cannot auto-detect encoding, not enough chars
at org.glassfish.json.UnicodeDetectingInputStream.detectEncoding(UnicodeDetectingInputStream.java:130)
at org.glassfish.json.UnicodeDetectingInputStream.(UnicodeDetectingInputStream.java:75)
at org.glassfish.json.JsonParserImpl.(JsonParserImpl.java:95)
at org.glassfish.json.JsonReaderImpl.(JsonReaderImpl.java:73)
at org.glassfish.json.JsonReaderFactoryImpl.createReader(JsonReaderFactoryImpl.java:71)
at org.glassfish.json.jaxrs.JsonValueBodyReader.readFrom(JsonValueBodyReader.java:93)
at org.glassfish.json.jaxrs.JsonValueBodyReader.readFrom(JsonValueBodyReader.java:66)
at org.glassfish.jersey.message.internal.ReaderInterceptorExecutor$TerminalReaderInterceptor.invokeReadFrom(ReaderInterceptorExecutor.java:257)
at org.glassfish.jersey.message.internal.ReaderInterceptorExecutor$TerminalReaderInterceptor.aroundReadFrom(ReaderInterceptorExecutor.java:236)
at org.glassfish.jersey.message.internal.ReaderInterceptorExecutor.proceed(ReaderInterceptorExecutor.java:156)
at org.glassfish.jersey.server.internal.MappableExceptionWrapperInterceptor.aroundReadFrom(MappableExceptionWrapperInterceptor.java:73)
at org.glassfish.jersey.message.internal.ReaderInterceptorExecutor.proceed(ReaderInterceptorExecutor.java:156)
at org.glassfish.jersey.message.internal.MessageBodyFactory.readFrom(MessageBodyFactory.java:1091)
at org.glassfish.jersey.message.internal.InboundMessageContext.readEntity(InboundMessageContext.java:874)
at org.glassfish.jersey.server.ContainerRequest.readEntity(ContainerRequest.java:271)
at org.glassfish.jersey.server.internal.inject.EntityParamValueParamProvider$EntityValueSupplier.apply(EntityParamValueParamProvider.java:97)
at org.glassfish.jersey.server.internal.inject.EntityParamValueParamProvider$EntityValueSupplier.apply(EntityParamValueParamProvider.java:80)
at org.glassfish.jersey.server.spi.internal.ParamValueFactoryWithSource.apply(ParamValueFactoryWithSource.java:74)
at org.glassfish.jersey.server.spi.internal.ParameterValueHelper.getParameterValues(ParameterValueHelper.java:92)
at org.glassfish.jersey.server.model.internal.JavaResourceMethodDispatcherProvider$AbstractMethodParamInvoker.getParamValues(JavaResourceMethodDispatcherProvider.java:133)
at org.glassfish.jersey.server.model.internal.JavaResourceMethodDispatcherProvider$VoidOutInvoker.doDispatch(JavaResourceMethodDispatcherProvider.java:183)
at org.glassfish.jersey.server.model.internal.AbstractJavaResourceMethodDispatcher.dispatch(AbstractJavaResourceMethodDispatcher.java:103)
at org.glassfish.jersey.server.model.ResourceMethodInvoker.invoke(ResourceMethodInvoker.java:493)
at org.glassfish.jersey.server.model.ResourceMethodInvoker.apply(ResourceMethodInvoker.java:415)
at org.glassfish.jersey.server.model.ResourceMethodInvoker.apply(ResourceMethodInvoker.java:104)
at org.glassfish.jersey.server.ServerRuntime$1.run(ServerRuntime.java:277)
at org.glassfish.jersey.internal.Errors$1.call(Errors.java:272)
at org.glassfish.jersey.internal.Errors$1.call(Errors.java:268)
at org.glassfish.jersey.internal.Errors.process(Errors.java:316)
at org.glassfish.jersey.internal.Errors.process(Errors.java:298)
at org.glassfish.jersey.internal.Errors.process(Errors.java:268)
at org.glassfish.jersey.process.internal.RequestScope.runInScope(RequestScope.java:289)
at org.glassfish.jersey.server.ServerRuntime.process(ServerRuntime.java:256)
at org.glassfish.jersey.server.ApplicationHandler.handle(ApplicationHandler.java:703)
at org.glassfish.jersey.grizzly2.httpserver.GrizzlyHttpContainer.service(GrizzlyHttpContainer.java:377)
at org.glassfish.grizzly.http.server.HttpHandler$1.run(HttpHandler.java:224)
at org.glassfish.grizzly.threadpool.AbstractThreadPool$Worker.doWork(AbstractThreadPool.java:593)
at org.glassfish.grizzly.threadpool.AbstractThreadPool$Worker.run(AbstractThreadPool.java:573)
at java.lang.Thread.run(Thread.java:748)
```
Using:
* Oracle JDK 1.8.0_144
* Jersey 2.26
* org.glassfish.jersey.containers:jersey-container-grizzly2-http
* org.glassfish.jersey.inject:jersey-hk2
* org.glassfish.jersey.media:jersey-media-json-processing
Contributor guide
Research direction
Start at org.glassfish.jersey.jsonp.JsonValueBodyReader.readFrom, following the stack trace into JsonReaderImpl and the failing UnicodeDetectingInputStream path. Reproduce the issue with the two curl commands using a single-digit JSON body and compare behavior with the charset parameter. Done means JsonProcessingFeature accepts the request and delivers the JSON value without the encoding exception.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- java
- Domain
- api, backend
- Issue type
- Bug
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100