Announcement Announcement Module
Collapse
No announcement yet.
Spring MVC and exception handlers Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Spring MVC and exception handlers

    Hi,

    I try to develop an handler to catch all exceptions from my service layer to convert them ( with i18n ) to errors in order to show them in the current page.
    Is there already this mechanism implemented in Spring MVC? Is there classes to represent errors ( like Errors for the validation )?
    Thanks for your help,
    Thierry

  • #2
    This is how we are doing this. We extend RuntimeException and store

    /** key to error text found in messages.properties file */
    private String errorProperty;
    /** Object array that will be used if there are any variables in the error text */
    private Object[] values;
    /** If the errorProperty key is not found in messages.properties this default value will be used as the error text instead */
    private String defaultMessage;

    public String getErrorMessage(int index, javax.servlet.http.HttpServletRequest request)
    {
    ResourceBundleMessageSource r = new ResourceBundleMessageSource();
    r.setBasename("messages");
    Locale locale = RequestContextUtils.getLocale(request);
    return r.getMessage(errorProperty,values,defaultMessage,l ocale);
    }

    In the Error Handler code we just call getErrorMessage on the error to get the correct message.

    Comment


    • #3
      Thanks for your answer.
      How can I configure a SimpleMappingExceptionResolver in Spring XML configuration file? Which class must I implement?
      As a matter of fact I'm looking for a complete example...
      Thierry

      Comment


      • #4
        public class ApplicationErrorHandler implements HandlerExceptionResolver, Ordered
        {
        protected final Log logger = LogFactory.getLog(getClass());
        private int order;

        /**
        * <p>Handles all unhandled ApplicationErrors</p>
        * <p>Displays error messages and a back link</p>
        */
        public ModelAndView resolveException(HttpServletRequest request,
        HttpServletResponse response,
        Object handler,
        Exception e)
        {
        if (e instanceof ApplicationError)
        {
        ApplicationError x = (ApplicationError)e;
        Map myModel = new HashMap();
        int size = x.getErrorMsgSize();
        ArrayList messages = new ArrayList();
        for (int i = 0; i < size; i++)
        {
        messages.add(x.getErrorMessage(i,request));
        }
        myModel.put("messages", messages);
        return new ModelAndView("Message", "model", myModel);
        }
        else
        return null;
        }

        /**
        * Used by spring configuration to decide the order that the handler will be invokes
        * in relation to other handlers
        */
        public int getOrder()
        {
        return order;
        }

        public void setOrder(int order)
        {
        this.order = order;
        }
        }

        In your config xml file...

        <bean id="handler1" class="com.scsis.presentation.common.ApplicationEr rorHandler">
        <property name="order"><value>1</value></property>
        </bean>

        Comment


        • #5
          Hi bobmanc,

          Thanks a lot for your answer. That's exactly what I need...
          Thierry

          Comment


          • #6
            Hi,
            is there any way how to direct the error handler to the same view (eg if the exception was thrown after submission of a form, display the errors in the view with the form)?

            Thank you very much

            Peter

            Comment


            • #7
              Hi Peter,

              I think that it's to you to develop it ;-)

              The object that resolveException gives you, is the instance of the controler where exception occurs.

              public class MyExceptionHandler implements
              HandlerExceptionResolver,Ordered {
              private int order;

              public ModelAndView resolveException(HttpServletRequest request,
              HttpServletResponse response,Object handler,Exception e) {
              ...
              }
              ...
              }

              I think that you can use an interface on your controler that must implements to give the name of the return of the form. Depending on the thrown exception ( or you want to do ), you can put it in ModelAndView objet with the description of the exception.
              If the controler doesn't implement the interface, you can forward on a default page to show errors and / or exceptions messages.
              Hope it helps you,
              Thierry

              Comment


              • #8
                Hi Thierry,
                thanks for hints - I will check it out and try to figure out the returning view based on that.

                Anyways, this is only a part of my bigger question about the business layer validation. I wouldn't want to couple business logic validation (e.g. checking credit status for customer who placed the order, etc.) with the presentation layer. However, I am not sure how to invoke a validation object (implementing Validator) from business layer and (mainly) propagate the possible 'rejections' to the presentation layer.

                All the examples use just overly simple validation testing only if the value is present (which is okay to invoke from presentation layer), however, I need to figure out where to put the 'real' validation in order to go WITH the Spring architecture and not against it

                Thanks for help

                Peter

                Comment


                • #9
                  your last question is quite different one from what was asked originally and should probably be addresses on the architecture forum.

                  But here are a few thoguhts:

                  Your business layer should throw 2 kinds of exceptions, checked and unchecked.

                  If your BL is throwing a checked exception, it usually means that the user is capable of fixing the error by providing different parameters on the request (hopefully thru a form you designed). In this case you should be able to report to the user what was the problem and redisplay the form for resubmission.

                  If your BL throws the runtime exception (unchecked), there is really nothing you can do about ... from your presentation layer developer's perspective. So, just design an exception page and inform the user of the fact that there is something wrong with the system they should try again later or relogin and try again the same operation or design your own way of dealing with the situation.

                  Now back to your question about BL validation. We have to look here at the kinds of validations you would regularly perform on your presentation layer (PL) and on your business layer. If you think about it, it is quite obvious they are very different.

                  PL validations are lightweight (by this I mean they usually need no db connection, no server-side resources, etc.) and they can very often be performed on the client side alltogether, without the need for roundtrip to the server. Theese are validations for required fields and dates being in an acceptable format, and required fields if another field is specified, etc. That is the reason you see examples of them, that seemingly not giving you the real life examples. They actually are real life but only for PL of your system. Now if you turn to the BL of your system that is what's usuall missing from the examples or maybe not emphasized enough.

                  BL validation is different, because you really need to make sure that for example you can add a new item to the collection that is owned by some containing entity. Another good example would be to check for the validity of the email address by contacting the mail server of the destination email server and asking if the email is valid (note: this will not always work, because some servers are not online all the time :-)). Contrast this with the validation of the email by simply looking for the @ sign to be there and ending in (.com, .edu ...), which is obviously a PL validation. BL can validate against simple stuff just like the PL did, but not neccesarily so, since if you have your BL collocated with your PL you will know for sure that the PL already did the validation so you can skip it in BL. However, if the BL is accessible by different PLs (think of web PL, rich client PL or some B2B agent accessing your business layer), you can not trust the validity of the data sent to you (think of the B2B agent), you will have to include the simple validation in your BL too. This is where optimization you talked about (propagating the validations to the BL) would be usefull.

                  So, to wrap up the post it basically all boils down to what is the architecture of your system. Where each of the parts are and how much you can trust the agent that is accessing you BL. My guess is that the majority of the projects is probably falling into the category of collocated PL and BL so no duplication of validations needed, and spring is pretty good at this kind of stuff. If you have a different design you will need to think of what are the validation that you will have to perform and where to place your optimizations

                  HTH

                  Comment


                  • #10
                    Originally posted by bpolka
                    your last question is quite different one from what was asked originally and should probably be addresses on the architecture forum.

                    But here are a few thoguhts:

                    Your business layer should throw 2 kinds of exceptions, checked and unchecked.

                    If your BL is throwing a checked exception, it usually means that the user is capable of fixing the error by providing different parameters on the request (hopefully thru a form you designed). In this case you should be able to report to the user what was the problem and redisplay the form for resubmission.

                    If your BL throws the runtime exception (unchecked), there is really nothing you can do about ... from your presentation layer developer's perspective. So, just design an exception page and inform the user of the fact that there is something wrong with the system they should try again later or relogin and try again the same operation or design your own way of dealing with the situation.

                    Now back to your question about BL validation. We have to look here at the kinds of validations you would regularly perform on your presentation layer (PL) and on your business layer. If you think about it, it is quite obvious they are very different.

                    PL validations are lightweight (by this I mean they usually need no db connection, no server-side resources, etc.) and they can very often be performed on the client side alltogether, without the need for roundtrip to the server. Theese are validations for required fields and dates being in an acceptable format, and required fields if another field is specified, etc. That is the reason you see examples of them, that seemingly not giving you the real life examples. They actually are real life but only for PL of your system. Now if you turn to the BL of your system that is what's usuall missing from the examples or maybe not emphasized enough.

                    BL validation is different, because you really need to make sure that for example you can add a new item to the collection that is owned by some containing entity. Another good example would be to check for the validity of the email address by contacting the mail server of the destination email server and asking if the email is valid (note: this will not always work, because some servers are not online all the time :-)). Contrast this with the validation of the email by simply looking for the @ sign to be there and ending in (.com, .edu ...), which is obviously a PL validation. BL can validate against simple stuff just like the PL did, but not neccesarily so, since if you have your BL collocated with your PL you will know for sure that the PL already did the validation so you can skip it in BL. However, if the BL is accessible by different PLs (think of web PL, rich client PL or some B2B agent accessing your business layer), you can not trust the validity of the data sent to you (think of the B2B agent), you will have to include the simple validation in your BL too. This is where optimization you talked about (propagating the validations to the BL) would be usefull.

                    So, to wrap up the post it basically all boils down to what is the architecture of your system. Where each of the parts are and how much you can trust the agent that is accessing you BL. My guess is that the majority of the projects is probably falling into the category of collocated PL and BL so no duplication of validations needed, and spring is pretty good at this kind of stuff. If you have a different design you will need to think of what are the validation that you will have to perform and where to place your optimizations

                    HTH

                    Comment


                    • #11
                      Hi Alex (the name you used at signature),

                      Thanks for the really elaborate insight into the problem. I very much agree with everything you said...I definatelly should have been more verbose when putting up my question

                      From the 3 different type of exceptions you are describing (BL checked, unchecked and the lightweight PL exceptions), my question was concerning the checked exceptions. As you mention, one way of addressing the issue would be 'collocating' the PL and BL layers - with one really major 'however' - this type of architecture would introduce very tight coupling between the PL and BL as well as it would require the BL to make certain assumptions about the PL. Unfortunately, this wouldn't be a very feasible way in my case, because I have to keep my PL more flexible - both technology-wise (sometimes it's spring sometimes Struts, sometimes Tapestry, etc.) as well as supporting different sub-types of 'web' clients. That makes my BL really a not trusting type

                      Also, this coupled way would make the testing of BL more complicated, as usually I start with the test case for all sorts of unsuccessful and successful paths. Only after I am done with that I move to presentation layer (which is possibly handled by somebody else on the team).

                      I was quite surprised not to find much discussion / examples on this type of validation which raised some doubts that maybe there's a better way to handle it in Spring (just like many other things that have really useful 'hooks' for many kinds of common situations).

                      Nevertheless, the mechanics of my existing validation are very similar to that of Spring (just implement a Validation interface, etc.) so since they look so similar I thought of possibly merging them into one...which is where the problem with 'more elegant' propagation cropped up.


                      Peter

                      Comment


                      • #12
                        Anything changed since last time?

                        Hi,

                        I encountered same problem as one discussed on this topic a time ago. I am hoping that with time the built-in solution exists yet.

                        I am not able to handle checked (recoverable) exceptions comming from BL for whose I want to show the previous view with original form and error message indicating the business error. Form should prevent submited (already validated) fields so I need the original form object in the model for the view.

                        Standard SimpleExceptionHandler does not provide this as it only puts exception to the model. To be honest the only thing that comes to my mind is that I wrap my exception to BindException and leverage existing <spring:bind> ${status.errorMessages} mechanism for bind and validation errors.

                        I am asking for cleaner solution. For example I am not happy with catching BL exceptions in every method of my controllers.

                        Thank you,
                        Michal

                        Comment

                        Working...
                        X