quarkus: unable to deserialize GregorianCalendar
Describe the bug
An attempt to deserialize a GregorionCalendar will lead to a Caused by: java.io.StreamCorruptedException: invalid type code: 00
Expected behavior
serialization should be supported for GregorianCalendar.
Actual behavior
2021-09-26 15:45:36,799 ERROR [io.qua.ver.htt.run.QuarkusErrorHandler] (executor-thread-0) HTTP Request to /hello/ser failed, error id: 7f645550-6c23-487a-9e7f-ea7baf2ea212-1: org.jboss.resteasy.spi.UnhandledException: java.io.StreamCorruptedException: invalid type code: 00
at org.jboss.resteasy.core.ExceptionHandler.handleApplicationException(ExceptionHandler.java:106)
at org.jboss.resteasy.core.ExceptionHandler.handleException(ExceptionHandler.java:372)
at org.jboss.resteasy.core.SynchronousDispatcher.writeException(SynchronousDispatcher.java:218)
at org.jboss.resteasy.core.SynchronousDispatcher.invoke(SynchronousDispatcher.java:519)
at org.jboss.resteasy.core.SynchronousDispatcher.lambda$invoke$4(SynchronousDispatcher.java:261)
at org.jboss.resteasy.core.SynchronousDispatcher.lambda$preprocess$0(SynchronousDispatcher.java:161)
at org.jboss.resteasy.core.interception.jaxrs.PreMatchContainerRequestContext.filter(PreMatchContainerRequestContext.java:364)
at org.jboss.resteasy.core.SynchronousDispatcher.preprocess(SynchronousDispatcher.java:164)
at org.jboss.resteasy.core.SynchronousDispatcher.invoke(SynchronousDispatcher.java:247)
at io.quarkus.resteasy.runtime.standalone.RequestDispatcher.service(RequestDispatcher.java:73)
at io.quarkus.resteasy.runtime.standalone.VertxRequestHandler.dispatch(VertxRequestHandler.java:135)
at io.quarkus.resteasy.runtime.standalone.VertxRequestHandler$1.run(VertxRequestHandler.java:90)
at io.quarkus.vertx.core.runtime.VertxCoreRecorder$13.runWith(VertxCoreRecorder.java:543)
at org.jboss.threads.EnhancedQueueExecutor$Task.run(EnhancedQueueExecutor.java:2449)
at org.jboss.threads.EnhancedQueueExecutor$ThreadBody.run(EnhancedQueueExecutor.java:1478)
at org.jboss.threads.DelegatingRunnable.run(DelegatingRunnable.java:29)
at org.jboss.threads.ThreadLocalResettingRunnable.run(ThreadLocalResettingRunnable.java:29)
at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
at java.lang.Thread.run(Thread.java:829)
at com.oracle.svm.core.thread.JavaThreads.threadStartRoutine(JavaThreads.java:567)
at com.oracle.svm.core.posix.thread.PosixJavaThreads.pthreadStartRoutine(PosixJavaThreads.java:192)
Caused by: java.io.StreamCorruptedException: invalid type code: 00
at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1710)
at java.io.ObjectInputStream.readArray(ObjectInputStream.java:2077)
at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1667)
at java.io.ObjectInputStream.defaultReadFields(ObjectInputStream.java:2464)
at java.io.ObjectInputStream.defaultReadObject(ObjectInputStream.java:629)
at java.util.Calendar.readObject(Calendar.java:3587)
at java.lang.reflect.Method.invoke(Method.java:566)
at java.io.ObjectStreamClass.invokeReadObject(ObjectStreamClass.java:1175)
at java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:2325)
at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:2196)
at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1679)
at java.io.ObjectInputStream.readObject(ObjectInputStream.java:493)
at java.io.ObjectInputStream.readObject(ObjectInputStream.java:451)
at org.acme.getting.started.GreetingResource.serdeser(GreetingResource.java:48)
at org.acme.getting.started.GreetingResource.serstring(GreetingResource.java:31)
at java.lang.reflect.Method.invoke(Method.java:566)
at org.jboss.resteasy.core.MethodInjectorImpl.invoke(MethodInjectorImpl.java:170)
at org.jboss.resteasy.core.MethodInjectorImpl.invoke(MethodInjectorImpl.java:130)
at org.jboss.resteasy.core.ResourceMethodInvoker.internalInvokeOnTarget(ResourceMethodInvoker.java:660)
at org.jboss.resteasy.core.ResourceMethodInvoker.invokeOnTargetAfterFilter(ResourceMethodInvoker.java:524)
at org.jboss.resteasy.core.ResourceMethodInvoker.lambda$invokeOnTarget$2(ResourceMethodInvoker.java:474)
at org.jboss.resteasy.core.interception.jaxrs.PreMatchContainerRequestContext.filter(PreMatchContainerRequestContext.java:364)
at org.jboss.resteasy.core.ResourceMethodInvoker.invokeOnTarget(ResourceMethodInvoker.java:476)
at org.jboss.resteasy.core.ResourceMethodInvoker.invoke(ResourceMethodInvoker.java:434)
at org.jboss.resteasy.core.ResourceMethodInvoker.invoke(ResourceMethodInvoker.java:408)
at org.jboss.resteasy.core.ResourceMethodInvoker.invoke(ResourceMethodInvoker.java:69)
at org.jboss.resteasy.core.SynchronousDispatcher.invoke(SynchronousDispatcher.java:492)
... 17 more
How to Reproduce?
create a sample application.
Add the following endpoint:
@GET
@Produces(MediaType.TEXT_PLAIN)
@Path("/ser")
public String ser() throws IOException, ClassNotFoundException {
GregorianCalendar calendar = new GregorianCalendar();
calendar.setTimeInMillis(new Date().toInstant().toEpochMilli());
return "calendar:" + serdeser(calendar);
}
private String serdeser(Object obj) throws IOException, ClassNotFoundException {
byte[] bytes = null;
try (
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(baos)) {
oos.writeObject(obj);
oos.flush();
bytes = baos.toByteArray();
}
try (ByteArrayInputStream bais = new ByteArrayInputStream(bytes);
ObjectInputStream ois = new ObjectInputStream(bais)) {
return "" + ois.readObject();
}
}
Add the following serialization-config.json in src/main/resources:
[
{
"name": "sun.util.calendar.ZoneInfo"
}
]
Add the following directive:
<quarkus.native.additional-build-args>-H:SerializationConfigurationResources=serialization-config.json</quarkus.native.additional-build-args>
Add the following class:
@RegisterForReflection(serialization = true, targets = { ArrayList.class, String.class,
Calendar.class, GregorianCalendar.class, TimeZone.class, SimpleTimeZone.class
})
public class ReflectionConfig {
}
Start a new native build.
Launch the application.
Invoke curl http://localhost:8082/hello/ser
The exception is printed in the server console.
Note : the invocation works fine if the application is started in jvm mode:
$ curl http://localhost:8082/hello/ser
calendar:java.util.GregorianCalendar[time=1632671566284,areFieldsSet=true,areAllFieldsSet=false,lenient=true,zone=sun.util.calendar.ZoneInfo[id="Europe/Paris",offset=3600000,dstSavings=3600000,useDaylight=true,transitions=184,lastRule=java.util.SimpleTimeZone[id=Europe/Paris,offset=360
0000,dstSavings=3600000,useDaylight=true,startYear=0,startMode=2,startMonth=2,startDay=-1,startDayOfWeek=1,startTime=3600000,startTimeMode=2,endMode=2,endMonth=9,endDay=-1,endDayOfWeek=1,endTime=3600000,endTimeMode=2]],firstDayOfWeek=2,minimalDaysInFirstWeek=4,ERA=1,YEAR=2021,MONTH=8,W
EEK_OF_YEAR=38,WEEK_OF_MONTH=4,DAY_OF_MONTH=26,DAY_OF_YEAR=269,DAY_OF_WEEK=1,DAY_OF_WEEK_IN_MONTH=4,AM_PM=1,HOUR=5,HOUR_OF_DAY=17,MINUTE=52,SECOND=46,MILLISECOND=284,ZONE_OFFSET=3600000,DST_OFFSET=3600000]
Output of uname -a or ver
No response
Output of java -version
No response
GraalVM version (if different from Java)
No response
Quarkus version or git rev
2.3.0.CR1
Build tool (ie. output of mvnw --version or gradlew --version)
No response
Additional information
About this issue
- Original URL
- State: closed
- Created 3 years ago
- Comments: 22 (22 by maintainers)
I was able to easily reproduce this even directly with the
native-imageand a trivial (non-Quarkus) Java application. So this looks like a bug in native-image itself. I’ll report it in the graal repo with a reproducer for their inputs.I think you should probably adapt
ReflectiveHierarchyBuildItem. It mostly does what you want but would need to be adapted for serialization. It doesn’t handle exceptions though.