[ 
https://issues.apache.org/jira/browse/CXF-7368?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
 ]

Lukas Rohner updated CXF-7368:
------------------------------
    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:
{noformat}
  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();
  }
{noformat}

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:
{noformat}
    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; 
    }
{noformat}

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:
{noformat}
        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;
    }
{noformat}

  was:
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:
{noformat}
  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();
  }
{noformat}

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:
{noformat}
    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; 
    }
{noformat}

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 
mehtod it should actually check if there is and 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.


> JAXB provider is handling non-jaxb classes
> ------------------------------------------
>
>                 Key: CXF-7368
>                 URL: https://issues.apache.org/jira/browse/CXF-7368
>             Project: CXF
>          Issue Type: Bug
>          Components: JAX-RS
>    Affects Versions: 3.1.11
>            Reporter: Lukas Rohner
>
> 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:
> {noformat}
>   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();
>   }
> {noformat}
> 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:
> {noformat}
>     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; 
>     }
> {noformat}
> 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:
> {noformat}
>         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;
>     }
> {noformat}



--
This message was sent by Atlassian JIRA
(v6.3.15#6346)

Reply via email to