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?

 

 

 

From: <[email protected]> on behalf of Michael Günnewig 
<[email protected]>
Reply-To: "[email protected]" 
<[email protected]>
Date: Thursday, October 19, 2017 at 05:39
To: Swagger <[email protected]>
Subject: Various Swagger 1.5.16 issues with JAXB, Jersey 1.x/2.x and Swagger-UI 
2.x and 3.x

 

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

 

-- 
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 [email protected].
For more options, visit https://groups.google.com/d/optout.


-- 
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 [email protected].
For more options, visit https://groups.google.com/d/optout.

Reply via email to