Various Swagger 1.5.16 issues with JAXB, Jersey 1.x/2.x and Swagger-UI 2.x and 3.x

85 views
Skip to first unread message

Michael Günnewig

unread,
Oct 19, 2017, 8:39:08 AM10/19/17
to Swagger
Hi all.

I stumbled about a couple issues with using Swagger.io together with Jersey 1.x and 2.x.

The issues can be seen using he following resource methods and the used model classes:
  @ApiOperation(value="Return List<Item>",
                notes
="Let Jersey/JAXB do the element wrapping")
 
@GET
 
@Path("list")
 
@Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
 
public List<Item> getModels() {
   
return Arrays.asList(new Item("1", "foo"), new Item("2", "bar"));
 
}


 
@ApiOperation(value="Return Items, which contains List<Item>",
                notes
="JAXB annotations are used so that the result is semantical equivalent to List<Iterm> been returned")
 
@GET
 
@Path("items")
 
@Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
 
public Items getItems() {
   
return new Items(Arrays.asList(new Item("1", "foo"), new Item("2", "bar")));
 
}

@XmlRootElement(namespace="io.swagger.bug-test")
@XmlAccessorType(XmlAccessType.NONE)
public final class Item extends Object {
 
@XmlAttribute(required=true)
 
@XmlSchemaType(name="ID")
 
private String id;


 
@XmlElement(required=true)
 
private String value;
...
}

@XmlRootElement(name="items")

@XmlAccessorType(XmlAccessType.NONE)
public final class Items extends Object {
 
@XmlElement(namespace="io.swagger.bug-test")
 
private List<Item> item;
...
}



If we now request the swagger.yaml file for this REST API, we get this:
swagger: "2.0"

paths
:
 
/list:
    get:
      summary: "Return List<Item>"
      description: "Let Jersey/
JAXB do the element wrapping"
      operationId: "
getModels"
      produces:
      - "
application/json"
      - "
application/xml"
      parameters: []
      responses:
        200:
          description: "
successful operation"
          schema:
            type: "
array"
            items:
              $ref: "
#/definitions/Item"
 
/items:
   
get:
      summary
: "Return Items, which contains List<Item>"
      description
: "JAXB annotations are used so that the result is semantical equivalent\
        \ to List<Iterm> been returned"

      operationId
: "getItems"
      produces
:
     
- "application/json"
     
- "application/xml"
      parameters
: []
      responses
:
       
200:
          description
: "successful operation"
          schema
:
            $ref
: "#/definitions/Items"
definitions
:
 
Item:
    type
: "object"
    required
:
   
- "value"
    properties
:
      value
:
        type
: "string"
 
Items:
    type
: "object"
    properties
:
      item
:
        type
: "array"
        xml
:
         
namespace: "io.swagger.bug-test"
        items
:
          $ref
: "#/definitions/Item"
    xml
:
      name
: "items"


Using Swagger-UI 2.2.x or 3.0.x produces equivalent JSON examples matching the actual server output.

Using Swagger-UI 2.2.x for the XML example produces incorrect examples:
GET /list


<?xml version="1.0"?>
<Inline Model>
 
<value>string</value>
</
Inline Model>


GET
/items


<?xml version="1.0"?>
<items xmlns="io.swagger.bug-test">
 
<item>
   
<value>string</value>
  </
item>
</items>


You can see that the "/list" case is producing totally corrupted XML, which has nearly nothing to do with the real one.
While the "/items" case is much better already, is it incorrect with respect to namespaces and lacks the id attribute of <item>.

Expected would have been:
GET /list



<?xml version="1.0" encoding="UTF-8"?>
<items>
 
<ns:item xmlns:ns="io.swagger.bug-test" id="string">
   
<value>string</value>
  </
ns:item>
</items>




GET /
items


<?xml version="1.0" encoding="UTF-8"?>
<items>
 
<ns:item xmlns:ns="io.swagger.bug-test" id="string">
   
<value>string</value>
  </
ns:item>
</items>


The <items> and <value> elements have no namespace defined and so reside in the default empty namespace.  Just the <item> element belongs to the specified namespace {io.swagger.bug-test}.

As the Swagger-UI 3.x does not honor "xml" within the "items" section, I have moved it into the item definition itself as then 2.x and 3.x will use it.  This manual produces YAML produces the correct XML examples if we assume that the default namespace just applies to the XML element that defines it and to none of its children in contrast to normal XML:
swagger: "2.0"

paths
:
 
/list:
    get:
      summary: "Return List<Item>"
      description: "Let Jersey/
JAXB do the element wrapping"
      operationId: "
getModels"
      produces:
      - "
application/json"
      - "
application/xml"
      parameters: []
      responses:
        200:
          description: "
successful operation"
          schema:
            type: "
array"
            xml:
              wrapped: "
true"
              name: "
items"
            items:
              $ref: "
#/definitions/Item"
 
/items:
   
get:
      summary
: "Return Items, which contains List<Item>"
      description
: "JAXB annotations are used so that the result is semantical equivalent\
        \ to List<Iterm> been returned"

      operationId
: "getItems"
      produces
:
     
- "application/json"
     
- "application/xml"
      parameters
: []
      responses
:
       
200:
          description
: "successful operation"
          schema
:
            $ref
: "#/definitions/Items"
definitions
:
 
Item:
    type
: "object"
    required
:
   
- "value"
    properties
:
      id
:
        type
: "string"
        xml
:
          attribute
: "true"
      value
:
        type
: "string"
    xml
:
      name
: "item"
     
namespace: "io.swagger.bug-test"
 
Items:
    type
: "object"
    properties
:
      item
:
        type
: "array"
        items
:
          $ref
: "#/definitions/Item"
    xml
:
      name
: "items"


With the above YAML specification the 2.x and 3.x Swagger UIs produce the following XML examples for both methods, which is much closer to the actual XML received:
<?xml version="1.0" encoding="UTF-8"?>

<items>
 
<item xmlns="io.swagger.bug-test" id="string">
   
<value>string</value>
 
</item>
</items>


As reference the actual Jersey output is:
GET /list

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<items>
 
<ns2:item xmlns:ns2="io.swagger.bug-test" id="1">
   
<value>foo</value>
  </
ns2:item>
 
<ns2:item xmlns:ns2="io.swagger.bug-test" id="2">
   
<value>bar</value>
  </
ns2:item>
</items>



GET /
items

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<items xmlns:ns2="io.swagger.bug-test">
 
<ns2:item id="1">
   
<value>foo</value>
  </
ns2:item>
 
<ns2:item id="2">
   
<value>bar</value>
  </
ns2:item>
</items>


As the issue also applies if the Jersey 1.x framework is been used and is independent of the Swagger UI version been used, would I think that the issue resides in the swagger-core and swagger-jaxrs packages.

The io.swagger.converter.ModelConverters.readAsProperty(Type) is been invoked for the response types, but has not means to pass this information to the MovelConverter.resolveProperty method, so that the io.swagger.jackson.ModelConverter can not add the "wrapped" flag.

Note also that if the name parameter to the @XmlRootElement of the Items class is left out, that the incorrect "Items" name is used instead by Swagger.

Also the @XmlAttribute annotations do not seem to be honoured.

And if no namespace is defined within any @XmlElement or @XmlRootElement, the one from the @XmlSchema is been used if any, otherwise the empty string is been used.  This is not correctly implemented by the Swagger side either, as well as if the namespace is explicitly set to an empty string with the @XmlSchema defined as package level.

So in summary:
- @XmlAttribute is not used by swagger-core
- namespace="" is not applied correctly if @XmlSchema is used at package-level
- @ApiOperation which return some collection, like List<Object>, lack "xml: {wrapped:true}" and the correct XML name for the wrapper
  This seems to be covered already by https://github.com/swager-api/swagger-core/issues/2334

  Regards,
    Michael

Ron Ratovsky

unread,
Oct 19, 2017, 2:20:53 PM10/19/17
to swagger-sw...@googlegroups.com

Thanks for the elaborate investigation.

Since there’s a ticket opened for the second issue you mentioned, would you mind opening one for the first issue?

--
You received this message because you are subscribed to the Google Groups "Swagger" group.
To unsubscribe from this group and stop receiving emails from it, send an email to swagger-swaggers...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Michael Günnewig

unread,
Oct 20, 2017, 9:53:25 AM10/20/17
to Swagger
Sure, provided some example code repository at https://github.com/dranuhl/swagger-bug-examples/, which had been used by myself to reproduce issue 2334 outside of my normal code base before I actually found it.  During that effort stumbled over the other mentioned issues, so that they are included in there as well.

Created Swagger-Core Issues:
Issue 2487 for @XmlAttribute and @XmlAccessorType(XmlAccessType.NONE) issue
Issue 2488 for XML namespace issue

  Regards,
    Michael

Michael Günnewig

unread,
Oct 23, 2017, 5:25:48 AM10/23/17
to Swagger
Issue 2487 is actually a duplicate of #1847, for which even a pull request #2409 exists, which has not been included yet.
Reply all
Reply to author
Forward
0 new messages