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

400 errors generated by a ValidationException are returning default error page instead of the Bean Validation's response entity #2945

Closed
jerseyrobot opened this issue Oct 1, 2014 · 11 comments

Comments

@jerseyrobot
Copy link
Contributor

400 errors generated by a javax.validation.ValidationException are returning
(Grizzly's) default error page (html) instead of the Bean Validation's
response entity (json). I've tried a ClientResponseFilter and its entityStream
also contains the html error page.
I have put a test project up on github. I asked on Stackoverflow (http://tinyurl.com/o7oou85) and one of
the Grizzly guys says that this is Jersey's behaviour -
org.glassfish.jersey.message.internal.CommittingOutputStream#flushBuffer(boolean) - writes JSON error message to the Servlet OutputStream
and
org.glassfish.jersey.servlet.internal.ResponseWriter#commit() - if data has been written to the response buffer, but not returned to the client (i.e. the response is not committed), the data in the response buffer must be cleared and replaced with the data set by these methods ...

I would like some configuration setting that would allow choice between
the default error page or the Bean Validation's response entity.

Environment

GrizzlyHttpServerFactory + Jersey + Bean Validation (jersey-container-grizzly2-servlet/jersey-bean-validation ver 2.12, grizzly-http-server ver 2.3.16, hibernate-validator ver 5.0.0.Final)

Affected Versions

[2.13]

@jerseyrobot
Copy link
Contributor Author

@glassfishrobot Commented
Reported by mwnorman

@jerseyrobot
Copy link
Contributor Author

@glassfishrobot Commented
Was assigned to michalgajdos

@jerseyrobot
Copy link
Contributor Author

@glassfishrobot Commented
File: grizzly-error-page-master.zip
Attached By: @AdamLindenthal

@jerseyrobot
Copy link
Contributor Author

@glassfishrobot Commented
@AdamLindenthal said:
Hi mwnorman,

Thanks for submitting the issue. I've just attached your github example to it. And I also edited your description a bit (so that links work etc.), hope you don't mind.

The issue will be now moved to backlog and we will take a look at it in one of the future sprints.

Regards,
Adam

@jerseyrobot
Copy link
Contributor Author

@glassfishrobot Commented
jendib said:
This issue seems to also affect custom WebApplicationException (https://jersey.java.net/documentation/2.15/representations.html#d0e6501).
I tried all the latest Jersey releases, and this bug was introducted in 2.11 (2.10.1 is OK), if this can help.

@jerseyrobot
Copy link
Contributor Author

@glassfishrobot Commented
michalgajdos said:
Do you still see this issue? I am somehow not able to reproduce it.

@jerseyrobot
Copy link
Contributor Author

@glassfishrobot Commented
Marked as fixed on Monday, July 27th 2015, 2:17:20 am

@jerseyrobot
Copy link
Contributor Author

@glassfishrobot Commented
rodierc said:
Hi Michael,

As a workaround, I found the combination of these three obscure settings gave me back a REST response that is JSON and not the HTML error pages (at a somewhat high productivity cost.) Perhaps you have this flag set?

In my view the error pages should be a result that is disabled, if you start the GrizzlyHttpServer in code, by default it should return whatever Jersey returns, not filter or alter the output with any HTML pages, simplifying this issue. Turning it on should be one flag.

The most important, and not well documented of them, is setting the custom ErrorrPageGenerator, overriding the default Grizzly Error Page Generator.

This is on Jersey = 2.21, Grizzly = 2.3.22.

<dependency>
            <groupId>org.glassfish.grizzly</groupId>
            <artifactId>grizzly-http-all</artifactId>
            <version>2.3.22</version>
        </dependency>

1. Set an init parameter that is non-obvious "do what you should do by default"

servletRegistration.setInitParameter(ServerProperties.RESPONSE_SET_STATUS_OVER_SEND_ERROR, "true");

2. Add an 'ErrorPageGenerator', overwriting the default Error Page Genenerator (now basically hacking into Jersey and Grizzly internals, to get it to return JSON errors for a REST Container?)

ErrorPageGenerator epg = new ErrorPageGenerator(){
			@Override
			public String generate(Request request, int status, String reasonPhrase,
								   String description, Throwable exception) {

				StringBuilder sb = new StringBuilder();

				sb.append(reasonPhrase);

				if (exception != null) {
					ByteArrayOutputStream baos = new ByteArrayOutputStream();
					PrintStream ps = new PrintStream(baos);
					exception.printStackTrace(ps);
					ps.close();
					sb.append(new String(baos.toByteArray()));
				}

				// already logged by Exception handlers 				// System.out.println(sb.toString()); 				return sb.toString();
			}
		};

		server.getServerConfiguration().setDefaultErrorPageGenerator(epg);

3. Return a Response object with Bad Request (which is the 400 code I want exposed to the users, not 200), with a custom object inside containing an error message property:

@Consumes(MediaType.APPLICATION_JSON)
	@Produces(MediaType.APPLICATION_JSON)
	@PUT
	@Path("/submitOrder")
	public Response sendNewOrder(SubmitOrder order) throws CustomReasonPhraseException {
		log.warn("Order Received via REST: " + order);
		String resultCodeString = null;

		try {
			resultCodeString = OrderSender.getInstance().sendOrder(order);
		} catch (Throwable t) {
			return Response.status(Response.Status.BAD_REQUEST.getStatusCode()).entity(makeErrorResult(t)).build();
		}

		log.warn("Done processing submit order: " + order+" returning success.");
		return Response.ok(makeSuccessResult(resultCodeString)).build();

This seems like a decent size hack, to simply return the results of an Exception inside the server, as a 400/500 error + JSON error message. I tried working with custom exception mappers, but still Grizzly would resolve these to HTML 500 or HTML 400 error pages. Notably returning http response code 0 would surpass these pages, but 400 / 500 is the standard I needed to adhere to.

Thanks for looking, hope it helps, Chris

@jerseyrobot
Copy link
Contributor Author

@glassfishrobot Commented
jendib said:
The issue has been fixed in 2.20 and above.
I tested it and it works just fine.

@jerseyrobot
Copy link
Contributor Author

@glassfishrobot Commented
This issue was imported from java.net JIRA JERSEY-2673

@jerseyrobot
Copy link
Contributor Author

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant