Uploaded image for project: 'CXF'
  1. CXF
  2. CXF-2997

CXF JAX-RS not thread safe when accessing multiple destinations concurrently

    XMLWordPrintableJSON

Details

    • Bug
    • Status: Closed
    • Blocker
    • Resolution: Fixed
    • 2.2.10
    • 2.3, 2.2.11
    • JAX-RS, Transports
    • None

    Description

      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/myservice/uris (blocked), and finally http://127.0.0.1:8085/two/myservice/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?

      Attachments

        1. cxf-rest-test.tar.gz
          2 kB
          Ate Douma

        Activity

          People

            Unassigned Unassigned
            ate Ate Douma
            Votes:
            0 Vote for this issue
            Watchers:
            1 Start watching this issue

            Dates

              Created:
              Updated:
              Resolved: