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

JAXB provider is handling non-jaxb classes

    XMLWordPrintableJSON

    Details

    • Type: Bug
    • Status: Closed
    • Priority: Major
    • Resolution: Fixed
    • Affects Version/s: 3.1.11
    • Fix Version/s: 3.1.12, 3.0.14, 3.2.0
    • Component/s: JAX-RS
    • Labels:
      None
    • Estimated Complexity:
      Unknown

      Description

      The default JSONProvider is trying to marshal a non-jaxb class which results in a 500 response of my endpoint.

      One of my endpoints is returning a StreamingOutput object to the response object:

        public static Response okJson(JValue json) {
          return Response.ok(new StreamingOutput() {
            @Override
            public void write(OutputStream s) throws IOException, WebApplicationException {
              try (final BufferedOutputStream bs = new BufferedOutputStream(s)) {
                serializer.fn.toJson(json).apply(bs);
              }
            }
          }, MediaType.APPLICATION_JSON_TYPE).build();
        }
      

      Unfortunately, the default JSONProvider is trying to marshal this class because it thinks it is a jaxb supported class. This support check happens in the AbstractJAXBProvider class:

          protected boolean isSupported(Class<?> type, Type genericType, Annotation[] anns) {
              if (jaxbElementClassMap != null && jaxbElementClassMap.containsKey(type.getName())
                  || isSkipJaxbChecks()) {
                  return true;
              }
              return isXmlRoot(type)
                  || JAXBElement.class.isAssignableFrom(type)
                  || objectFactoryOrIndexAvailable(type)
                  || (type != genericType && objectFactoryForType(genericType))
                  || org.apache.cxf.jaxrs.utils.JAXBUtils.getAdapter(type, anns) != null;
          
          }
      
          protected boolean objectFactoryOrIndexAvailable(Class<?> type) {
              return type.getResource("ObjectFactory.class") != null
                     || type.getResource("jaxb.index") != null; 
          }
      

      The issue is that the objectFactoryOrIndexAvailable is returning true which doesn't indicate that the type itself is a jaxb class. To fix the support method it should actually check if there is a jaxb.index file and if in the index file the current type is available. Then we can clearly say it's a jaxb supported class.

      Something like this:

              return isXmlRoot(type)
                  || JAXBElement.class.isAssignableFrom(type)
                  || (objectFactoryOrIndexAvailable(type) && indexContainsType(type))
                  || (type != genericType && objectFactoryForType(genericType))
                  || org.apache.cxf.jaxrs.utils.JAXBUtils.getAdapter(type, anns) != null;
      
          protected boolean indexContainsType(Class<?> type) {
            try (BufferedReader reader = new BufferedReader(new InputStreamReader(type.getResourceAsStream("jaxb.index")))) {
              String line = null;
              while((line = reader.readLine()) != null) {
                if(line.contains(type.getName()))
                  return true;
              }
            }
            return false;
          }
      

        Attachments

          Activity

            People

            • Assignee:
              sergey_beryozkin Sergey Beryozkin
              Reporter:
              lrohner Lukas Rohner
            • Votes:
              0 Vote for this issue
              Watchers:
              2 Start watching this issue

              Dates

              • Created:
                Updated:
                Resolved: