Description of problem: If we have a web application that has a JAX-RS resource and another interface not related to JAX-RS (servlet or a JAX-WS web service, for example), but using resteasy client, we might have an issue where: If the JAX-RS endpoint is acessed and it is doing the providers registration; At the same time, the other endpoint that uses the client request API is accessed; The GZIPDecodingInterceptor will be registered twice The consequence is that two GZIPDecodingInterceptor will try to parse the GZIP requests corrupting the gzipinputstream and leading to the following error everytime we try to use the client again: Caused by: java.util.zip.ZipException: Not in GZIP format at java.util.zip.GZIPInputStream.readHeader(GZIPInputStream.java:164) [rt.jar:1.7.0_97] at java.util.zip.GZIPInputStream.<init>(GZIPInputStream.java:78) [rt.jar:1.7.0_97] at java.util.zip.GZIPInputStream.<init>(GZIPInputStream.java:90) [rt.jar:1.7.0_97] at org.jboss.resteasy.plugins.interceptors.encoding.GZIPDecodingInterceptor$FinishableGZIPInputStream.<init>(GZIPDecodingInterceptor.java:30) at org.jboss.resteasy.plugins.interceptors.encoding.GZIPDecodingInterceptor.read(GZIPDecodingInterceptor.java:47) at org.jboss.resteasy.core.interception.MessageBodyReaderContextImpl.proceed(MessageBodyReaderContextImpl.java:109) at org.jboss.resteasy.plugins.interceptors.encoding.GZIPDecodingInterceptor.read(GZIPDecodingInterceptor.java:51) at org.jboss.resteasy.core.interception.MessageBodyReaderContextImpl.proceed(MessageBodyReaderContextImpl.java:109) The issue, as greatly found by our colleague Dennis, is that the client request will try to create a wrapped provider during the other providerfactory provider registration. which means that the following synchronized code block from RegisterBuiltin class won't protect us: public class RegisterBuiltin { public static void register(ResteasyProviderFactory factory) { synchronized (factory) { if (factory.isBuiltinsRegistered() || !factory.isRegisterBuiltins()) return; try { registerProviders(factory); } catch (Exception e) { throw new RuntimeException(e); } factory.setBuiltinsRegistered(true); } } //.... Version-Release number of selected component (if applicable): How reproducible: In "real world" it is really hard to reproduce this, but we can force a stop at the mentioned point to reproduce it; Steps to Reproduce: 1.Build the attached application; 2. Deploy the attached application in JBoss EAP 6.4.7 with some mechanism to stop the server execution at RegisterBuiltin::register method (I used a debugger, but byteman can be used as well); 3. Access the REST endpoint: **http://localhost:8080/resteasy-provider-threadsafe/servlet** 4. While the thread is stuck at the provider registration, access the servlet that uses the resteasy client library: **http://localhost:8080/resteasy-provider-threadsafe/servlet** You should see the error Actual results: Exception every time when a new request is made; Expected results: Not exception. Additional info: The reproducer is here: https://github.com/jesuino/reproducers/tree/master/JBEAP-8428resteasy-provider-threadsafe I would like also to add that: This is not reproducible on EAP 7.0.3 - the reason is that resteasy seems to be started eagerly by default I can't access the servlet when I have the breakpoint on register method There's a fixed JIRA that will probably fix this as well - the issue was fixed on EAP 7.0.1, however, I didn't have the change to backport it: https://issues.jboss.org/browse/JBEAP-4703 Notice that even if JBEAP-4703 fix the problem, our main issue here is that the provider factory is not thread safe in this circumstance. If you say that the fix for JBEAP-4703 is okay to fix it, we can simply backport it to 6.x branches. Thanks!
As noted in the upstream Jira https://issues.jboss.org/browse/JBEAP-8428 , this issue has a workaround that consists in: 1. Making the app get initialized eagerly through adding ResteasyBootstrap listener to the app's web.xml: <web-app> <listener> <listener-class>org.jboss.resteasy.plugins.server.servlet.ResteasyBootstrap</listener-class> </listener> </web-app> 2. Making the web subsystem to postpone opening the connectors through setting the org.apache.catalina.connector.WAIT_FOR_BEFORE_START system property to the context path of the given application. This can be done either on command line bin/standalone.sh -Dorg.apache.catalina.connector.WAIT_FOR_BEFORE_START=/my-app1,/my-app2 or in standalone.xml <system-properties> <property name="org.apache.catalina.connector.WAIT_FOR_BEFORE_START" value="/my-app1,/my-app2"/> </system-properties> or via cli: bin/jboss-cli.sh --connect command="/system-property=org.apache.catalina.connector.WAIT_FOR_BEFORE_START:add(value=/my-app1,/my-app2)"
Closing as there is a workaround, we will fix this upstream