[
https://issues.apache.org/jira/browse/CXF-2997?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
]
Ate Douma updated CXF-2997:
---------------------------
Attachment: cxf-rest-test.tar.gz
Simple maven test project to expose the problem.
To compile and start the test webapp just execute:
$mvn jetty:run
Then from two different browser windows invoke the following requests:
1) http://127.0.0.1:8085/two/lock (browser window 1)
2) http://localhost:8085/one/uris (browser window 2)
3) http://127.0.0.1:8085/two/unlock (browser window 1)
Resulting output from browser window 2:
BaseUri on entry: http://localhost:8085/one/
BaseUri on exit : http://127.0.0.1:8085/two/
> CXF JAX-RS not thread safe when accessing multiple destinations concurrently
> -----------------------------------------------------------------------------
>
> Key: CXF-2997
> URL: https://issues.apache.org/jira/browse/CXF-2997
> Project: CXF
> Issue Type: Bug
> Components: JAX-RS, Transports
> Affects Versions: 2.2.10
> Reporter: Ate Douma
> Priority: Blocker
> Attachments: cxf-rest-test.tar.gz
>
>
> If a (single) JAX-RS service is invoked concurrently for different
> destinations, the CXF ServletController and ServletTransportFactory
> implementations override the current Destination state between these
> invocations.
> I have created a simple test web application using Spring to expose this
> problem.
> My example ServiceImpl.java looks like:
> @Path("/myservice/")
> @Produces("application/xml")
> public class ServiceImpl {
> volatile boolean locked;
> @GET
> @Path("/uris")
> @Produces("text/plain")
> public String getUris(@Context UriInfo uriInfo) {
> StringBuilder uris = new StringBuilder("BaseUri on entry:
> "+uriInfo.getBaseUri().toString()).append("\n");
> try {
> while (locked) {
> Thread.sleep(1000);
> }
> }
> catch (Exception x) {}
> return uris.append("BaseUri on exit : " +
> uriInfo.getBaseUri().toString()).append("\n").toString();
> }
>
> @GET
> @Path("/lock")
> @Produces("text/plain")
> public String lock() {
> locked = true;
> return "locked";
> }
> @GET
> @Path("/unlock")
> @Produces("text/plain")
> public String unlock() {
> locked = false;
> return "unlocked";
> }
> And in my web.xml I defined two CXFServlet mappings as follows:
> <servlet-mapping>
> <servlet-name>CXFServlet</servlet-name>
> <url-pattern>/one/*</url-pattern>
> </servlet-mapping>
> <servlet-mapping>
> <servlet-name>CXFServlet</servlet-name>
> <url-pattern>/two/*</url-pattern>
> </servlet-mapping>
> Finally, in Spring ApplicationContext.xml I setup the jaxrs server like this:
> <jaxrs:server id="myService" address="/">
> <jaxrs:serviceBeans>
> <ref bean="serviceImpl" />
> </jaxrs:serviceBeans>
> <jaxrs:extensionMappings>
> <entry key="xml" value="application/xml" />
> </jaxrs:extensionMappings>
> </jaxrs:server>
> <bean id="serviceImpl" class="service.ServiceImpl" />
> As can be seen from the ServicesImpl.java, I used a trick to temporarily
> "lock" and "unlock" a call to /myservice/uris from another request using
> /myservice/lock and /myservice/unlock.
> Without locking, a call to http://localhost:8085/one/myservice/uris produces
> the expected following result:
> BaseUri on entry: http://localhost:8085/one/
> BaseUri on exit : http://localhost:8085/two/
> However, if I first call http://localhost:8085/one/myservice/lock, then
> http://localhost:8085/one/uris (blocked), and finally
> http://127.0.0.1:8085/two/unlock (note the different hostname 127.0.0.1 and
> servletPath /two) I get the following result:
> BaseUri on entry: http://localhost:8085/one/
> BaseUri on exit : http://127.0.0.1:8085/two/
> Clearly, UriInfo.getBaseURI() isn't thread safe as is shown above.
> After debugging a bit the current (CXF 2.2.10) implementation of the
> ServletController and ServletTransportFactory, it looks like the
> ServletController.updateDests(HttpServletRequest) method and the
> ServletTransportFactory as a whole don't maintain resolved Destination state
> isolated per request.
> Our CXF (JAX-RS) application exposes the same REST service to be called from
> many different addresses (hosts) as well as upfront unknown servlet paths,
> this really is a blocking issue.
> To be more concrete, we have to use a request wrapper to dynamically "mount"
> the same rest service for different urls (its a front end for a unlimited
> hierarchical resources repository).
> Is there an easy way to protect JAX-RS service interactions from concurrent
> invocations, e.g. by using special configurations, or is this indeed a
> serious bug which will have to be fixed first?
--
This message is automatically generated by JIRA.
-
You can reply to this email to add a comment to the issue online.