Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Open
developersorli opened this issue Jun 19, 2024 · 0 comments

Comments

@developersorli
Copy link

developersorli commented Jun 19, 2024

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/[email protected]/swagger-ui.css\" />\r\n" + "  </head>\r\n"
						+ "  <body>\r\n" + "  <div id=\"swagger-ui\"></div>\r\n" + "  <script src=\"https://unpkg.com/[email protected]/swagger-ui-bundle.js\" crossorigin></script>\r\n"
						+ "  <script src=\"https://unpkg.com/[email protected]/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
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant