swagger-api / swagger-api/swagger-ui

SRVE8115W: WARNING: Cannot set status. Response already - problem on Request with array element does not generate Yaml request

Open
#10,032 2 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
JavaScript
Stars
29k
Forks
9.3k
Avg merge
2d 23h
Merged PRs (30d)
25

Description

Q&A (please complete the following information)
  • OS: Windows 10
  • Browser: [chrome, safari]
  • Version: [2.2.22]
  • Method of installation: [maven]
  • Swagger-UI version: [5.10.5]
  • Swagger/OpenAPI version: [Swagger 2.2, OpenAPI 3.0]
Describe the bug you're encountering

We generate yaml file from code - Down to top. Here is example how to produce issue.:

Content & configuration

Steps to reproduce the behavior:

public class RequestWithArray  implements Serializable {
	protected Integer id;
..
        protected List<Address> address; // problem throw exception SRVE8115W: WARNING: Cannot set status. Response already committed.
..
//getters and setters
...
}
public class Address implements Serializable {
	protected String street;
        protected List<Name> name; // problem throw exception SRVE8115W: WARNING: Cannot set status. Response already 
..
..
//getters and setters
...
}
@SecurityRequirement(name = "basicAuth")
@Tag(name="service", description="service API")
@Path("/service")
public class Service {

	@Context
	private UriInfo uriInfo;

	@Context
	private ServletContext servletContext;

	@POST
	@Consumes(MediaType.APPLICATION_JSON)
	@Produces(MediaType.APPLICATION_JSON)
	@Path("/createService")
	@Operation(security = @SecurityRequirement(name = "basicAuth"), summary = "Creates ....",
    responses = { @ApiResponse(responseCode = "200", description = "OK_MSG",
                    content = @Content()),
                    @ApiResponse(responseCode = "404", description = "Not found"),
				    @ApiResponse(responseCode = "401", description = "Unauthorized"),
				    @ApiResponse(responseCode = "400", description = "Bad request")})
	public Response createService(RequestWithArray request, final @QueryParam("dateCreated") String dateCreated, final @QueryParam("id") Integer id, final @QueryParam("number") String number, @Parameter(in = ParameterIn.HEADER,
		    name =  "authorization",
		    example = "Basic token-id",
		    required = true) @HeaderParam("authorization") String authToken,  @HeaderParam("userId") String userId, @Context HttpHeaders headers) {

...
}
public class ApiServlet extends OpenApiServlet {

	@Context
	private UriInfo uri;

	// TODO move to own servlet non jaxrs project and reference from there
	// TODO cleanup and errors
	@Override
	protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

		String acceptHeader = req.getHeader(ACCEPT_HEADER);

		if (!StringUtils.isBlank(acceptHeader) && acceptHeader.toLowerCase().contains("text/html")) {

			if (req.getRequestURI().toString().toLowerCase().endsWith("html")) {
				String url = ServletUriComponentsBuilder.fromRequestUri(req).replacePath(null).build().toUriString() + req.getRequestURI().replaceFirst("([^/]+)?$", "");

				String val = "<!DOCTYPE html>\r\n" + "<html lang=\"en\">\r\n" + "  <head>\r\n" + "    <meta charset=\"utf-8\" />\r\n"
						+ "    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\" />\r\n" + "    <meta\r\n" + "      name=\"description\"\r\n" + "      content=\"SwaggerUI\"\r\n"
						+ "    />\r\n" + "    <title>SwaggerUI</title>\r\n" + "    <link rel=\"stylesheet\" href=\"https://unpkg.com/swagger-ui-dist@5.10.5/swagger-ui.css\" />\r\n" + "  </head>\r\n"
						+ "  <body>\r\n" + "  <div id=\"swagger-ui\"></div>\r\n" + "  <script src=\"https://unpkg.com/swagger-ui-dist@5.10.5/swagger-ui-bundle.js\" crossorigin></script>\r\n"
						+ "  <script src=\"https://unpkg.com/swagger-ui-dist@5.10.5/swagger-ui-standalone-preset.js\" crossorigin></script>\r\n" + "  <script>\r\n" + "    window.onload = () => {\r\n"
						+ "      window.ui = SwaggerUIBundle({ " + "      url: '" + url + "openapi.json',\r\n" + "        dom_id: '#swagger-ui',\r\n" + "        validatorUrl : null,\r\n" + "        presets: [\r\n"
						+ "          SwaggerUIBundle.presets.apis,\r\n" + "          SwaggerUIStandalonePreset\r\n" + "        ],\r\n" + "        layout: \"StandaloneLayout\",\r\n" + "      });\r\n"
						+ "    };\r\n" + "  </script>\r\n" + "  </body>\r\n" + "</html>";
				try (PrintWriter pw = resp.getWriter()) {
					pw.write(val);
				}

				resp.setStatus(200);
				return;
			}
		}

		String ctxId = getContextIdFromServletConfig(getServletConfig());
		OpenApiContext ctx = OpenApiContextLocator.getInstance().getOpenApiContext(ctxId);
		OpenAPI oas = ctx.read();
		Info info = new Info().title("Swagger app").description("This is a server  documentation.").termsOfService("http://swagger.io")
				// .contact(new Contact().email("@swagger.io"))
				.version("1.0");

		oas.info(info);

		List<Server> serverList = new ArrayList<Server>();
		Server s = new Server();
		s.url("http://localhost:9080/service");
		s.description("localhost");
		serverList.add(s);
		
		/*
		 * SecurityRequirement securityItem = new SecurityRequirement(); securityItem. oas.addSecurityItem(securityItem);
		 */

		if (oas != null && ctx.getOpenApiConfiguration() != null) {
			if (ctx.getOpenApiConfiguration().getFilterClass() != null) {
				try {
					OpenAPISpecFilter filterImpl = (OpenAPISpecFilter) Class.forName(ctx.getOpenApiConfiguration().getFilterClass()).newInstance();
					SpecFilter f = new SpecFilter();
					oas = f.filter(oas, filterImpl, ServletUtils.getQueryParams(req.getParameterMap()), ServletUtils.getCookies(req.getCookies()), ServletUtils.getHeaders(req));
				} catch (Exception e) {
					LOGGER.error("failed to load filter", e);
				}
			}
		}

		String type = "json";

		// String acceptHeader = req.getHeader(ACCEPT_HEADER);
		/*
		 * if (!StringUtils.isBlank(acceptHeader) && acceptHeader.toLowerCase().contains("text/html")) { type = "html"; } else
		 */if (!StringUtils.isBlank(acceptHeader) && acceptHeader.toLowerCase().contains(APPLICATION_YAML)) {
			type = "yaml";
		} else {
			// check URL:
			if (req.getRequestURL().toString().toLowerCase().endsWith("yaml")) {
				type = "yaml";
			}
		}

		boolean pretty = ctx.getOpenApiConfiguration() != null && Boolean.TRUE.equals(ctx.getOpenApiConfiguration().isPrettyPrint());

		resp.setStatus(200);

		if (type.equalsIgnoreCase("yaml")) {
			resp.setContentType(APPLICATION_YAML);
			try (PrintWriter pw = resp.getWriter()) {
				pw.write(pretty ? ctx.getOutputYamlMapper().writer(new DefaultPrettyPrinter()).writeValueAsString(oas) : ctx.getOutputYamlMapper().writeValueAsString(oas));
			}
		} else if (type.equalsIgnoreCase("json")) {
			resp.setContentType(APPLICATION_JSON);
			try (PrintWriter pw = resp.getWriter()) {
				pw.write(pretty ? ctx.getOutputJsonMapper().writer(new DefaultPrettyPrinter()).writeValueAsString(oas) : ctx.getOutputJsonMapper().writeValueAsString(oas));
			}
		}

	}

}

To reproduce...
  1. Go to web page swagger ui
  2. Click on click service. It Try generate request body, but web page freeze.
  3. Si error: It throws warning: SRVE8115W: WARNING: Cannot set status. Response already
Expected behavior

Expect that will generate request example

Screenshots
Additional context or thoughts

1.If you remove in class RequestWithArray line:

protected List<Address> address; 
//and getters and setters
...

and in class Address

protected List<Name> name;
//and getters and setters
...
  1. Then works, but missing functionality

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start from the Swagger UI operation request-body generation reached by clicking the service in the supplied reproduction, using Swagger UI 5.10.5 and the nested Java List

and List model. Compare behavior with those fields removed and verify that the request example is generated without the SRVE8115W warning or a frozen page.

Written by the indexing model from the issue text.

Assessment

Tech stack
java, javascript
Domain
api, frontend
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Needs clarification
Newbie friendliness
25/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.