I created my custom exception class by extending WebApplicationException class of jax-rs api. I am throwing this exception on wrong inputs.
public class RestException extends WebApplicationException {
public RestException(String message, Response.Status status) {
super(message, status);
}
}
When I used above exception in my application, it is returning the status code correctly, but it is not returning the error message i set in the constructor.
If i use jersey instead of cxf, it is showing both error message and status code. Any help on this....
I get rid of the problem by changing the signature of RestException constructore like below.
public class RestException extends WebApplicationException {
public RestException(String message, Response.Status status) {
super(Response.status(status).entity(message).type(MediaType.TEXT_PLAIN).build());
}
}
Related
I want to set custom error Message for Unrecognized field and others errors with request body.
I tried ExceptionMapper but it dont work :/
Using quarkus and Jackson
public class ReqDTO {
private String a;
}
when send request:
{
"a": "a"
}
its look good. But when send:
{
"a": "a",
"b": "b"
}
have error response:
Unrecognized field "b"; (class ReqDTO), not marked as ignorable
Want customize this message and other bad json body (like too much fields) to own message like "BAD_JSON_SCHEMA".
Tried
#Provider
public class ExHandler implements ExceptionMapper<JsonMappingException>{
public Respone toResponse(JsonMappingException e) {
//response bad field impl
}
}
But its not work. Looks like a json handle exception faster. Tried with "Exception", "JsonParseException" but nothing changed :/
#Path("/")
public class Controller {
#Post
#Consume(APPLICATION_JSON)
#Produces(TEXT_PLAIN)
public Response getA(#Valid ReqDTO reqDTO){
//logic
}
}
#Edit
Found something like DeserializationProblemHandler but dont know how change message for handleUnknownProperty :/
#Singleton
RegisterCustomModuleCustomizer implements ObjectMapperCustomizer {
public void customize(ObjectMapper mapper){
mapper.addHandler(new DeserializationProblemHandler(){
#SneakyThrows
#Override
public boolean handleUnknownProperty(...... params){
throw new ApplicationException("ERRO_BODY_MESS");
}
}
}
}
#Provider
public class ExHandler implements ExceptionMapper<ApplicationException>{
public Respone toResponse(ApplicationException ex) {
return Response.status(BAD_REQUEST).entity(ex.getMessage()).build();
}
}
I made an ExceptionMapper to catch and log all exceptions, like:
#Provider
public class CatchAllExceptionsMapper implements ExceptionMapper<Throwable> {
private static final Logger LOG = LoggerFactory.getLogger(CatchAllExceptionsMapper.class);
#Override
public Response toResponse(Throwable exception) {
LOG.error("Exception not catched!", exception);
return Response.serverError().build();
}
}
It catches the Exceptions my code throws, but if I send a Request with a JSON value that throws an IllegalStateException at my object's creation, this ExceptionMapper is ignored and I get a 400 Bad Request Response.
Funny thing is this Response is not the traditional Tomcat HTML formatted Response, its just plain text. It say just:
Cannot construct instance of `com.example.vo.AutoValue_Customer$Builder`, problem: First name is null or empty. at [Source: (org.glassfish.jersey.message.internal.ReaderInterceptorExecutor$UnCloseableInputStream); line: 14, column: 1]
I thought this might be something short-circuiting Jersey, but my #PreMatching ContainerRequestFilter is executed beforehand, so I really have no idea why the 400 Response is not the traditional HTML one from Tomcat.
Why is this happening? What can I do to catch this and return my own Response?
As stated by Paul Samsotha in the comments, JacksonFeature from the jersey-media-json-jackson package define some ExceptionMappers, like JsonMappingException and JsonParseException. The solution is to create our own, register them within the ResourceConfig and register JacksonFeature last, otherwise it won't work.
e.g.
#Provider
#Priority(1) // hack for overriding other implementations.
public class JsonMappingExceptionMapper implements ExceptionMapper<JsonMappingException> {
#Override
public Response toResponse(JsonMappingException exception) {
return Response.status(Status.BAD_REQUEST).build();
}
}
#Provider
#Priority(1) // hack for overriding other implementations.
public class JsonParseExceptionMapper implements ExceptionMapper<JsonParseException> {
#Override
public Response toResponse(JsonParseException exception) {
return Response.status(Status.BAD_REQUEST).build();
}
}
public class MyResourceConfig extends ResourceConfig {
public MyResourceConfig() {
register(CatchAllExceptionsMapper.class);
register(JsonMappingExceptionMapper.class);
register(JsonParseExceptionMapper.class);
register(JacksonFeature.class);
}
}
I want to have a central place to implement exceptions handling logic for specific type of exception.
If specific exception type occurs, I'd like to be able to run one of the following depending on internal configuration:
send message to error queue immediately without further second level retries;
hide the message, not sending it to both processing queue or error queue;
I've found this topic which covers first case but not second one, as a message would be put into error queue if we return TimeSpan.MinValue:
NServiceBus error handling
So how could I implement 2nd case? better both to be be implemented in one place, one class
Prior to version 6 of NServiceBus, you could use IManageMessageFailures to manage message failures. You can handle the case of a serialization exception or - more relevant to your problem at hand - when a message can not be handled gracefully after first-level retries are attempted.
Here's how to implement a custom FaultManager that'd ignore exceptions of certain type or send failed messages with other errors back to the error queue. Note that the First-Level retires still happens and this kicks-in instead of Second-Level retry.
public class IssueOrder : ICommand
{
public bool NotFound { get; set; }
public bool HasFaulted { get; set; }
}
public class OrderHandler : IHandleMessages<IssueOrder>
{
public void Handle(IssueOrder message)
{
if(message.NotFound)
throw new OrderNotFoundException();
if(message.HasFaulted)
throw new ApplicationException();
}
}
public class OrderNotFoundException : Exception
{
}
public class CustomFaultManager : IManageMessageFailures
{
private ISendMessages sender;
private MessageForwardingInCaseOfFaultConfig config;
private BusNotifications notifications;
private static ILog Logger = LogManager.GetLogger<CustomFaultManager>();
public CustomFaultManager(ISendMessages sender, IProvideConfiguration<MessageForwardingInCaseOfFaultConfig> config)
{
this.sender = sender;
this.config = config.GetConfiguration();
}
public void SerializationFailedForMessage(TransportMessage message, Exception e)
{
}
public void ProcessingAlwaysFailsForMessage(TransportMessage message, Exception e)
{
if (e is OrderNotFoundException)
{
//Ignore the exception;
Logger.WarnFormat("OrderNotFoundException was thrown. Ignoring the message Id {0}.", message.Id);
}
else
{
//Check if you have performed enough retries, ultimately send to error queue
SendToErrorQueue(message, e);
}
}
private void SendToErrorQueue(TransportMessage message, Exception ex)
{
message.TimeToBeReceived = TimeSpan.MaxValue;
sender.Send(message, new SendOptions(config.ErrorQueue));
Logger.WarnFormat("Message {0} will was moved to the error queue.", message.Id);
}
public void Init(Address address)
{
}
}
And to register the custom FaultManager:
var config = new BusConfiguration();
//Other configuration code
config.RegisterComponents(c =>
{
c.ConfigureComponent<CustomFaultManager>(DependencyLifecycle.InstancePerCall);
});
In Version 6 of NServiceBus however, the IManageMessageFailures interface is deprecated. The new Recoverability api in version 6 allows for better customization, althrough there's no direct way of ignoring/muting an exception. For that purpose you need a custom behavior in the NServiceBUs pipeline and run it in a step between one of the known steps (e.g. before a message is moved to the error queue).
hey i am using Oleg Sych's solution for handling exception via WCF:
link
everything works well with Known Exceptions (such as InvalidOperationException and SystemException) but when i am trying to use my own custom exception, it doesnt work and i get the following wcf exception:
"There was an error reading from the pipe: The pipe has been ended. (109, 0x6d)"
this is my custom exception:
[KnownType(typeof(SessionExpiredException))]
[global::System.Serializable]
[DataContract]
public class SessionExpiredException : Exception
{
public SessionExpiredException() { }
public SessionExpiredException(string message) : base(message) { }
public SessionExpiredException(string message, Exception inner) : base(message, inner) { }
protected SessionExpiredException(
System.Runtime.Serialization.SerializationInfo info,
System.Runtime.Serialization.StreamingContext context)
: base(info, context) { }
}
what am i doing wrong? am i missing an attribute?
You don't need to model your custom error as an exception, but as a DataContract with DataMembers for the information you intent to return. Then, on the WCF service, just return a FaultException of your type.
This page has a good sample on how to model it:
http://msdn.microsoft.com/en-us/library/ms752208.aspx
public SessionExpiredException() { }
public SessionExpiredException(string message) : base(message) { }
public SessionExpiredException(string message, Exception inner) : base(message, inner) { }
protected SessionExpiredException(
System.Runtime.Serialization.SerializationInfo info,
System.Runtime.Serialization.StreamingContext context)
: base(info, context) { }
the above solution is WRONG.
How can I get my WCF service to communicate errors in a RESTful manner? Specifically, if the caller passes invalid query string parameters to my method, I'd like to have a 400 or 404 HTTP error returned to the user. When I search for HTTP error status in relation to WCF, all I can find are pages where people are trying to resolve errors they're receiving. I'd rather not just throw a FaultException, because that gets converted to a 500 error, which is not the correct status code.
I found a helpful article here: http://zamd.net/2008/07/08/error-handling-with-webhttpbinding-for-ajaxjson/. Based on that, this is what I came up with:
public class HttpErrorsAttribute : Attribute, IEndpointBehavior
{
public void AddBindingParameters(
ServiceEndpoint endpoint,
BindingParameterCollection bindingParameters)
{
}
public void ApplyClientBehavior(
ServiceEndpoint endpoint, ClientRuntime clientRuntime)
{
}
public void ApplyDispatchBehavior(
ServiceEndpoint endpoint, EndpointDispatcher endpointDispatcher)
{
var handlers = endpointDispatcher.ChannelDispatcher.ErrorHandlers;
handlers.Clear();
handlers.Add(new HttpErrorHandler());
}
public void Validate(ServiceEndpoint endpoint)
{
}
public class HttpErrorHandler : IErrorHandler
{
public bool HandleError(Exception error)
{
return true;
}
public void ProvideFault(
Exception error, MessageVersion version, ref Message fault)
{
HttpStatusCode status;
if (error is HttpException)
{
var httpError = error as HttpException;
status = (HttpStatusCode)httpError.GetHttpCode();
}
else if (error is ArgumentException)
{
status = HttpStatusCode.BadRequest;
}
else
{
status = HttpStatusCode.InternalServerError;
}
// return custom error code.
fault = Message.CreateMessage(version, "", error.Message);
fault.Properties.Add(
HttpResponseMessageProperty.Name,
new HttpResponseMessageProperty
{
StatusCode = status,
StatusDescription = error.Message
}
);
}
}
}
This allows me to add a [HttpErrors] attribute to my service. In my custom error handler, I can ensure that the HTTP status codes I'd like to send are sent.
If you are using standard WCF then FaultException is the correct approach to this. If you do not wish to do that and you want to be RESTful then you should use the REST WCF approach (Here is a quick start template for 4.0 and for 3.5). This fully supports returning HTTP Status Codes to the client.
I wanted to implement the same solution you are asking, the link below worked perfect when you want to play with HTTP status codes.
How can I return a custom HTTP status code from a WCF REST method?
There is a WebOperationContext that you can access and it has a OutgoingResponse property of type OutgoingWebResponseContext which has a StatusCode property that can be set.
WebOperationContext ctx = WebOperationContext.Current;
ctx.OutgoingResponse.StatusCode = System.Net.HttpStatusCode.OK;