swagger-maven-plugin: Wrong class in documentation generation

Hello,

I might be missing something, but in one of API endpoints, I implemented a PATCH operation, which takes a DocumentType as parameter. This is however one of our custom models, and not the DocumentType defined in several namespaces.

The import statements etc are all correct, as is the annotations. When running the maven build, my documentation get’s generated, however the output contains the wrong DocumentType class. It’s as if the plugin seems to take the first matching class, and not the one I specified.

About this issue

  • Original URL
  • State: closed
  • Created 6 years ago
  • Comments: 17 (6 by maintainers)

Most upvoted comments

not getting much difference unfortunately.

  1. I’ve removed the ModelConverter as requested, so the pom.xml was reduced in configuration.
  2. Updated my ApiReader to be even more simple, to not convert/change anything.
public class SwaggerExtendedApiReader extends JaxrsReader {

	public SwaggerExtendedApiReader(Swagger swagger, Log log) {
		super(swagger, log);
	}

	/**
	 * <p>
	 * Override the public read method, and enforce the reading of hidden operations.
	 * </p>
	 */
	@Override
	public Swagger read(Class<?> cls) {
		return read(cls, "", null, true, new String[0], new String[0], new HashMap<String, Tag>(), new ArrayList<Parameter>());
	}
}

So it simply exposes hidden APIs when it’s used, otherwise relies on the standard implementation. Swagger still seems to be using some kind of different class for the example unfortunately:

image

I have no idea to what this is being mapped, but it doesn’t resemble a single class we have in use for our code.

Tried setting the springmvc configuration to false, did not seem to have any direct result/difference on the generated documentation.

Here’s a link to the gist for the fully generated swagger file: https://gist.github.com/coding-bunny/56a586d425846faaea74817dca398fe5

Okay,

I’ve updated the plugin to 3.1.7, which took quite some effort due dependency conflicts I had to resolve on our side, but I succeeded. So now I’ve regenerated the swagger documentation on the 3.1.7.

This is the model that I have created:

public class DocumentType extends EntityModel {
	private boolean templateEnabled = false;
	private boolean ownersEnabled = false;
	private boolean uniqueIdEnabled = false;

	/**
	 * <p>
	 * Empty Constructor to support JAX-RS
	 * </p>
	 */
	public DocumentType() {

	}

	/**
	 * <p>
	 * Copy Constructor to support copying from the ICP model.
	 * </p>
	 *
	 * @param entity The {@link EntityModel} to copy from.
	 * @throws CMException Thrown when the copy fails
	 */
	public DocumentType(EntityModel entity) throws CMException {
		super(entity);

		boolean template = entity.getAttribute(CMItem.ATTRIBUTE_TEMPLATE_DETAILS) != null
				&& entity.getAttribute(CMItem.ATTRIBUTE_TEMPLATE_NAME) != null;
		boolean owners = entity.getChildEntities() != null && entity.getChildEntities().get(CMItem.ATTRIBUTE_MDS_OWNERS) != null;
		boolean uniqueId = entity.getAttributes().get(CMItem.ATTRIBUTE_MDS_ID) != null;

		setTemplateEnabled(template);
		setOwnersEnabled(owners);
		setUniqueIdEnabled(uniqueId);
	}

	/**
	 * <p>
	 * Sets whether templating is enabled for the Document Type or not.
	 * <b>This is for usage in the V1 API only</b>
	 * </p>
	 *
	 * @param enabled A boolean indicating whether templating is enabled or not.
	 */
	public void setTemplateEnabled(boolean enabled) {
		templateEnabled = enabled;
	}

	/**
	 * <p>
	 * Returns whether templating is enabled for the Document Type or not.
	 * <b>This is for usage in the V1 API only</b>
	 * </p>
	 *
	 * @return True if templating is enabled; otherwise false.
	 */
	@XmlElement(name = "templateEnabled")
	public boolean getTemplateEnabled() {
		return templateEnabled;
	}

	/**
	 * <p>
	 * Sets whether Ming.le Owners is enabled for the Document Type or not.
	 * <b>This is for usage in the V1 API only</b>
	 * </p>
	 *
	 * @param enabled A boolean indicating whether Owners is enabled or not.
	 */
	public void setOwnersEnabled(boolean enabled) {
		ownersEnabled = enabled;
	}

	/**
	 * <p>
	 * Returns whether Ming.le Owners is enabled for the Document Type or not.
	 * <b>This is for usage in the V1 API only</b>
	 * </p>
	 *
	 * @return True if Owners is enabled; otherwise false.
	 */
	@XmlElement(name = "ownersEnabled")
	public boolean getOwnersEnabled() {
		return ownersEnabled;
	}

	/**
	 * <p>
	 * Sets whether MDS_ID is enabled for the Document Type or not.
	 * <b>This is for usage in the V1 API only</b>
	 * </p>
	 *
	 * @param enabled A boolean indicating whether MDS_ID is enabled or not.
	 */
	public void setUniqueIdEnabled(boolean enabled) {
		uniqueIdEnabled = enabled;
	}

	/**
	 * <p>
	 * Returns whether MDS_ID is enabled for the Document Type or not.
	 * <b>This is for usage in the V1 API only</b>
	 * </p>
	 *
	 * @return True if MDS_ID is enabled; otherwise false.
	 */
	@XmlElement(name = "uniqueId")
	public boolean getUniqueIdEnabled() {
		return uniqueIdEnabled;
	}

	@Override
	public boolean equals(Object other) {
		if (other instanceof ValueSet) {
			return ((DocumentType) other).getName().equals(getName());
		} else {
			return false;
		}
	}

	@Override
	public int hashCode() {
		return getName().hashCode();
	}
}

The model inherits from a few classes that simply add more properties to it. There’s really nothing special about this class, as it’s just a data-container. In the upper classes a few properties are marked with @XmlElement to get the correct output generated etc.

The endpoint has been defined as follows:

@Produces(MediaType.APPLICATION_JSON)
@Path(RestUrls.BASE_URL_API_V1 + RestUrls.API_V1_DOCUMENT_TYPES_URL)
@Api(value = "DocumentTypes", hidden = true)
@Session(roles = { Role.ROLE_ADMINISTRATOR })
public class DocumentTypesResource {
	private static final GridLog LOGGER = GridLogger.getLogger(DocumentTypesResource.class);

	@Context private HttpServletRequest request;
@PATCH
	@ApiOperation(value = "Update an Entity", notes = "Updates the Entity inside IDM", response = DocumentType.class)
	@PublicApi
	@Path(RestUrls.API_V1_ENTITY_URL)
	@Session(roles = { Role.ROLE_ADMINISTRATOR })
	public Response update(@ApiParam(value = RestUrls.LANGUAGE_DESC, required = false) @QueryParam(RestUrls.LANGUAGE) String language,
			@ApiParam(value = "The name of the DocumentType to be updated.", required = true) @PathParam("name") String name,
			@ApiParam(value = "The JSON payload, representing the DocumentType.", required = true) DocumentType partialModel)
			throws CMException {
		RestHelper.logRequest(request, LOGGER);
		DocumentTypeService service = new DocumentTypeService(request, language);
		DocumentType modelToUpdate = service.read(name);

		service.update(modelToUpdate, partialModel);

		return CacheController.noCache(Response.ok().entity(service.read(name))).build();
	}
}

Basic Resource class that listen to incoming PATCH requests. Everything work perfectly when using the endpoint, so that’s not the problem. However when I look at the generated Swagger documentation, the following class is generated instead:

DocumentType {
  name (string, optional),
  notations (NamedNodeMap, optional),
  internalSubset (string, optional),
  entities (NamedNodeMap, optional),
  systemId (string, optional),
  publicId (string, optional),
  attributes (NamedNodeMap, optional),
  baseURI (string, optional),
  lastChild (Node, optional),
  namespaceURI (string, optional),
  nodeValue (string, optional),
  ownerDocument (Document, optional),
  previousSibling (Node, optional),
  textContent (string, optional),
  prefix (string, optional),
  nodeName (string, optional),
  childNodes (NodeList, optional),
  firstChild (Node, optional),
  nodeType (integer, optional),
  nextSibling (Node, optional),
  localName (string, optional),
  parentNode (Node, optional)
}

Which is a completely different class than the one I have defined. My guess is that the code is simply picking the first matching class based on name, completely ignoring the package.

Things I’ve tried:

  • specifying the fully qualified name
  • Using our custom annotation that overwrites the type