Page 2 of 3 FirstFirst 123 LastLast
Results 11 to 20 of 30

Thread: Conceptual: context information

  1. #11

    Default

    just a short comment on the "error" codes for exceptions.

    What i have at the moment is a code concept where the exception is not thrown bye a message but much more by a key. This is done to give the flexibility to change the Exception message with the text the developer desire, without the need of refactoring. There are no key/value pairs like structure.

    To be more specific, we have a ErrorDefinitionService witt the medho getErrorById(Long id) which is used like

    throw new MyException(errorService.getErrorById(longValue))) ;

    The reason why its called "Error" might be misleading but EVERY error displayed in the web application is automatically translated etc.

    The technical exceptions however dont need to be translated as they never reach the user in that form. In that case we only use it to avoid refactoring for error message editing.

  2. #12

    Default

    The AOP issue i could imagine an around advisor:

    Code:
    public class MyInterceptor   implements MethodInterceptor {
    
      public Object invoke(MethodInvocation methodInvocation) throws Throwable {
            Object call = null;
            try {
                call = methodInvocation.proceed();
            } catch (ContexualException e) {
               //get some context information
               e.addContexualInformation(context);
               throw e;
            }
            return result;
        }
    }
    and with the spring configuration and BeanNameAutoProxyCreator i could wildcard the beanNames to get this advisor work with all my Service objects as they all end with *Service

    On my Portlet Filter i could catch the ContextException and dispatch to the generic webpage with the standard error message or the UI with the BusinessException error message.

  3. #13
    Join Date
    Nov 2006
    Location
    Boston, MA
    Posts
    303

    Default

    A couple of things...

    1) I have slightly revisited the contextual exception class that I suggested earlier in this thread. I didn't like my using of a collection to store the context, if all we need is a complementary message that reflects the states of some arbtrary application objects that developers may add. So, here's the revised class:

    Code:
    package com.yourcompany.common;
    
    /**
     * This exception class allows storing contextual information on the exception instances. The contextual data may
     * be added to an exception instance as arbitrary application objects and written out as a simple string of toString()
     * representations of all stored objects.
     */
    public class ContextualException extends RuntimeException {
    
        private final StringBuilder contextMessage = new StringBuilder(1000);
    
        public ContextualException(String msg) {
            super(msg);
        }
    
        public ContextualException(String msg, Throwable t) {
            super(msg, t);
        }
    
        /**
         * Adds an object to the exception context string.
         * @param o application object whose content may be of interest in the context of this exception
         */
        public void addToContext(Object o) {
            contextMessage.append(o.toString()).append(System.getProperty("line.separator"));
        }
    
        /**
         * Adds an object and its description to the exception's context string.
         * @param o application object whose content may be of interest in the context of this exception
         * @param description clarifying description of the object being added to context
         */
        public void addToContext(Object o, String description) {
            contextMessage.append(description).append(": ").append(o);
        }
    
        /**
         * Gets the string representation of all objects stored in this exception's context.
         * @return concatenated string of all context object toString() representations
         */
        public String getContextMessage() {
            return contextMessage.toString();
        }
    }
    As you see, you have an option to add a description for each contextual object as well. I chose not to override the getMessage() method to include the context info by default because I don't think it would be appropriate. Let the clients decide when and how to use that information. See an example below...

    2) I see a little problem with your code example... How do you know that the method you are intercepting is throwing that specific type of exception. And what happens to all other exceptions that may be thrown inside. What you need to do is to catch any exception, wrap it into your ContextualException, add context data, and re-throw.

    Code:
    ...
    catch (Throwable t) {
               //get some context information
               // ...
               ContextualException ce = new ContextualException("Your generic message here: service failure, blah-blah...", t);
               // loop through args of the method 
               for (Object arg : allArgs) {
                   ce.addToContext(arg);
               }
               throw ce;
            }
    3) In your handler - if, for example, you are using Spring MVC in the front-end - you'd have a generic exception resolver for all your system errors that will catch all server-side exceptions that bubble up to it:

    Code:
    package com.yourcompany.common.web.springmvc;
    
    /**
     * This class implements an exception resolver that redirects to the designated view in cases of any exception that
     * <i>has not been previously caught and handled</i> by the application or framework (including any Spring Webflow error
     * handlers registered with the application). Those are any system and programming errors that should result in a
     * graceful termination of the application.
     * <p/>
     * A bean of this class must be registered with the Spring application context with the order number the highest amongst
     * all error resolvers. By default, the prioritization order value for this error handler is set to {@link
     * Integer#MAX_VALUE} to ensure that this resolver is evaluated <i>after</i> all other registered resolvers have been
     * considered for any exceptions that may require more specific handling. The value may be changed via the {@link
     * #setOrder} method, however, in most cases, that should not be done.
     */
    public class SystemErrorResolver implements HandlerExceptionResolver, Ordered {
    
        private int order = Integer.MAX_VALUE; // prioritization order number for this Ordered object
        private String errorViewName;
        private static final Logger logger = Logger.getLogger(SystemErrorResolver.class);
        private static final String ERR_MESSAGE =
                "Unrecoverable error occured in the application. See the nested exception stack trace for details. Redirecting to the Error View."
                ;
    
        /**
         * Constructs a SystemErrorResolver object with the given name of the view to render in the case of a system error.
         * This view name must be properly resolved by the Spring MVC DispatcherServlet's view resolver.
         *
         * @param viewName name of the View to render, to be resolved by the DispatcherServlet's ViewResolver
         */
        public SystemErrorResolver(String viewName) {
            errorViewName = viewName;
        }
    
        /** {@inheritDoc} */
        public ModelAndView resolveException(HttpServletRequest req, HttpServletResponse response, Object handler,
                                             Exception e) {
            // return the Error Page view in the case of any unhandled exception
            if (e != null) {
                logger.error(ERR_MESSAGE, e);
                
                // below is the additional logging of any context message if it is available
                if (e instance of ContextualException) {
                     logger.error(e.getContextInfo());
                }
                return new ModelAndView(errorViewName);
            } else {
                return null;
            }
        }
    
        /** {@inheritDoc} */
        public int getOrder() {
            return order;
        }
    
        /**
         * Sets the prioritization order number for this Ordered object. Spring looks at all handler exception resolvers
         * (beans implementing the appropriate HandlerExceptionResolver interface) in the application context. Any instances
         * that implement the Ordered interface are sorted (lowest order first), and others are added at the end of the
         * list. The resolvers are considered in the order they are listed.
         * <p/>
         * NOTE: By default, the prioritization order value for this error handler is set to {@link Integer#MAX_VALUE} to
         * ensure that this resolver is evaluated <i>after</i> all other registered resolvers have been considered for any
         * exceptions that may require more specific handling. <b>Do not call this method unless this behavior must
         * change.</b>
         *
         * @param num order number
         */
        public void setOrder(int num) {
            this.order = num;
        }
    
    }
    This is a class I wrote a few projects ago, and I have re-used it since on many projects. It's very basic stuff, I am sure you are familiar with it and know how to register an exception resolver with the Spring context. What I added just now, is the optional check for the exception instance being of the ContextualException type. If so, we can also log the context message.

    You could write a generic "Around" aspect for each public service method that would do something like that (assuming you have some common marker interface for all your services called IService, for example):

    Code:
       
        @Pointcut("execution(* com.yourcompany.common.service.IService.*(..))")
        private void anyServiceOperation() {
        }
    
    @Around("anyServiceOperation()")
    public static void handleServiceFailure(ProceedingJoinPoint point) {
            try {
                point.proceed();
            } catch (Throwable t) {
                ContextualException ce = new ContextualException(STD_MSG, t);
                for (Object arg : point.getArgs()) {
                     ce.addToContext(arg);
               }
               throw ce;
            }
        }
    This is just off the top of my head, and you certainly will need to work with it to make this do whatever you really need. But I hope this gives you the general idea. Let me know if this makes sense.

    Good luck,
    Constantine

  4. #14

    Default

    Thanks a lot for your input :-) your described structure is pretty much the one that i designed on paper atm :-)

    As we dont use the Spring MVC, the AOP approach is more suitable :-)

  5. #15
    Join Date
    Nov 2006
    Location
    Boston, MA
    Posts
    303

    Default

    Quote Originally Posted by uenluena View Post
    Thanks a lot for your input :-) your described structure is pretty much the one that i designed on paper atm :-)

    As we dont use the Spring MVC, the AOP approach is more suitable :-)
    Oh, one does not exclude the other... In fact, the Spring resolvers indeed implement aspect-like behavior. You register a resolver and spring ensures that it listens to the exceptions. Also, you need to use AOP to wrap pall your service-layer errors - something similar to what I showed you. Then, you can do whatever you like on the front-end as long as you make sure that your filter catches all exceptions. In fact, using an aspect in the service tier is more important because you would otherwise have to duplicate the same error-context-handling code in every public method on every service. On the front-end, you only need a single place for your try/catch.

    I have re-read your earlier comment about exception codes. I would implement that differently. Please bear with me... See, the String returned by getMessage() on an exception class is not meant to be seen by the user. This text is for error logging and analysis by developers and admins. That is why, the content of that message is only - and foremost - relevant in the context of the very code that throws that particular exception instance. Therefore, not only there is nothing wrong with hard-coding that text in the very call to the exception constructor before it is being thrown, it is the best and most appropriate approach. This is - by all means - part of your error-handling code and your diagnostics. The worst thing you can do is to extract those valuable messages from your code and hide them behind some crafty message-resolving mechanism. Now, you are robbing yourself and your developers from the ability to easily figure out what the exception represents even by looking directly at the code that throws it! Talk about over-engineering and maintenance nightmare. Please think well about what you guys are doing.

    The problem is that you are mixing two things that should not be mixed. When you construct an exception instance, always provide the most detailed technical message you can come up with - for debugging purposes. Never intend to expose this message to the end user. That message should not change with application refactorings because it must reflect one and only one very specific error condition. The exception itself must not contain anything that will ever be exposed to the user! Now, if you want to ease the way for the client to map an exception instance to a particular user-friendly message, and use the exception object itself to assist you with that, there is a better way to do it. (DISCLAIMER: Let me just say that this may not be such a good idea, generally. It's probably better - in most cases - to use external mappings rather than one built-in within an exception. Exceptions should ideally be agnostic of the outside world and only transport the error context.) Ok, here's one way...

    1) First of all, I am sure you agree that error messages that are meant for the end-user must be externalized, preferably in a message resource bundle where they are easily accessible and manageable during development or in production. I know you work with a bunch of DB who, I am sure, want to put everything into the database. Perhaps you can convince them to store user-oriented messages where they rightfully belong - in the presentation tier configuration: message resource files, where your config files, and both Java classes and JSPs can effortlessly access them.

    2) You may have your application-specific exception classes (the ones that, in your opinion represent business cases) extend some MsgResourceAwareException that stores the message key - in addition to the detail message and nested Throwable. (Note, I don't advocate this as a general-purpose solution, see my disclaimer above...) When you throw an instance of such exception, you set the message key that corresponds to a message in your message resource. Of course, this means that the classes that throw this type of exception should live in the same tier with the message resource, otherwise it gets ugly.

    3) Then, in your front-end filter, you check if the incoming exception is message-resource-aware, and if so, you retrieve the message key and put it into your request object. Redirect the app to the error page. (I am talking about your scenario when all errors direct to the same page but with different messages.)

    4) Your generic error JSP may look similar to the following:

    Code:
    <?xml version="1.0" encoding="UTF-8" ?>
    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
    <%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
    
    <%-- If no custom message key is passed in request, use standard default System Error messages; assign "messageKey" variable to default  --%>
       <c:if test="${messageKey == null}">
        <c:set var="messageKey" value="error.system.default"/>
       </c:if>
    
        <%-- retrieve message from msg resource by key and display --%>
        <fmt:message key="${messageKey}"/>
            
        <p/>
    
        ... place your buttons here, or whatever....
    That's it! When an error occurs, your technical note (produced by Exception.getMessage()) - along with the full stack trace - will be logged for the experts to look at. Your UI will display whatever message you have put into your message resource for this case. The only "fishy" thing here is that the developer needs to insert the appropriate message key into the exception instance and make that exception "aware" of the application that uses it. If you have architected your system properly, that business condition would be evaluated in the client (because it is the client's requirement to distinguish one error from another; your database should not be telling the client which messages to display and when!) So, there is no violation of architectural principles. If you try to introduce "user message keys" somewhere in the back end, well, then, it's just plain wrong, anyway.

    Ok, I hope you'll find at least some of this helpful, if not for the current project, then maybe for some future designs... Good luck!
    Last edited by constv; Nov 24th, 2008 at 02:39 PM.

  6. #16

    Default

    so your proposal would be to add contexual information to the exception but not resolve those errors e.g in the DAO layer with some errors texts from the DB, as those messages are ment for the Developer and not the users outside.

    A better approach would catch/throw your exceptions and add your message and context information into it and throw again, so no information from the error stack gets lost...correct me if im wrong ;-)

  7. #17
    Join Date
    Nov 2006
    Location
    Boston, MA
    Posts
    303

    Default

    Quote Originally Posted by uenluena View Post
    so your proposal would be to add contexual information to the exception but not resolve those errors e.g in the DAO layer with some errors texts from the DB, as those messages are ment for the Developer and not the users outside.

    A better approach would catch/throw your exceptions and add your message and context information into it and throw again, so no information from the error stack gets lost...correct me if im wrong ;-)
    Always keep in mind that an exception is meant to be a vehicle that efficiently transports the error information (as full as possible, for debugging and diagnostics purposes, not for user consumption) from the origin of the error to the designated handler - without imposing the error handling burden on any modules in between where it is not relevant. (Hence, checked exceptions are a nuisance.) It is not the job of the exception to carry any application-specific task (such as offering a presentation tier message that the app should display to the user.) It is up to the application itself to interpret the error type and map it to any appropriate application-specific action. A clean design must separate these two concepts.

    Add your technical/debug message + context explicitly in the code that throws the exception. Don't modify that exception any more - unless you can add even more useful debugging info to it between the originating code and the designated handler. In most cases, the latter is not necessary. However, in the case of your specific requirements, it is what you will do with your service-tier exceptions: you will intercept all Throwables that originated underneath the service at the service boundary (public method) with your aspect, add the service-specific context, and re-throw. Let it fly to the designated handler that will log it and transform it into the appropriate application action. If you need to map that exception to a specific presentation-tier message shown to the user, have the handler invoke the special resolver in the presentation tier that will do that. You will have to implement that resolver/mapper as a separate independent module injectable into your controllers. That resolver could be configured (through Spring) to map certain exception types to particular message keys. In other words, the resolver would store a map of "exception-class->msg-key" entries. You will be able to look up the key and drop it into the request object. if your resolver is aware of your request context, it may do it for you. The JSP would use the key to display the appropriate message from the message resource - as I showed you in an earlier post. Note that here I am talking about your specific case when you need to direct all your system exceptions to the same view but with distinct end-user messages. In a more generic solution, you will be mapping different exception classes to different views as well. However, in most real-world applications, you should have very few of such distinct conditions, while most your system exceptions would still need to result in the same generic error page.

    The bottom line: maintain/resolve your presentation tier messages in the front-end only. If you do store your user-friendly messages (that the app displays to the end user in its pages) in the database, then have a mechanism that loads and resolves them in the front end. I prefer to maintain such messages in the message resources rather than the database. But if you have to store them in the DB, you may, for example, cache them all at once in the PT when the application starts; or do a separate data-tier trip each such message. I would certainly try to avoid the latter.
    Last edited by constv; Nov 26th, 2008 at 09:28 AM.

  8. #18

    Default

    Im going through the different use cases at the moment to cover all of them in the exception handling concept.

    When i look at the exceptions that can occur in my application layers i have the following cases:

    DAO Layer
    Im using the support classes of Spring, so my DAO's are all throwing unchecked exceptions.

    There's nothing to do here. Those runtime exceptions shuld be catched late

    Service Layer
    As my DAO's are throwing unchecked exceptions, there's nothing i need to catch from my DAO's. There might be cases, where a DAO exception should be transformed to a checked exception but this is done in the try/catch where i will catch a runtime exception and throw a ServiceException.

    The specific exception which is thrown here is ServiceException. The service exception has an additional methode addContextualInformation(Object o) to add more context information to the service exception.

    Does it make sense to declare a throws ServiceException for each Service Method?

    Presentation Layer
    We're using JSF as the presentation technology. Managed/Backed beans that are doing calls to the Service methods can catch ServiceExceptions.


    Now with AOP i could catch RuntimeExceptions with a interceptor. My problem is that on JSF level there's also the possibility of raised RuntimeExceptions...so i need to catch those errors even higher....Any recommendations?

  9. #19
    Join Date
    Nov 2006
    Location
    Boston, MA
    Posts
    303

    Default

    DAO Layer
    Im using the support classes of Spring, so my DAO's are all throwing unchecked exceptions.

    There's nothing to do here. Those runtime exceptions shuld be catched late
    That's correct. Just focus on your DA logic and let any errors bubble up to be caught later where the application knows what to do with them.

    Service Layer
    As my DAO's are throwing unchecked exceptions, there's nothing i need to catch from my DAO's. There might be cases, where a DAO exception should be transformed to a checked exception but this is done in the try/catch where i will catch a runtime exception and throw a ServiceException.

    The specific exception which is thrown here is ServiceException. The service exception has an additional methode addContextualInformation(Object o) to add more context information to the service exception.

    Does it make sense to declare a throws ServiceException for each Service Method?
    Why do you need to convert anything into a checked exception in the service tier? Only catch those types of exceptions in the service tier that you feel you need to update with useful information. For such exceptions, catch them (perhaps using an aspect, as we have discussed), add a clarifying message and context parameters, wrap it into a service-tier Runtime exception and re-throw. Do not force the immediate caller of the service method to implement a try-catch. If your client code is written properly, a public method on your action/controller/managed bean/whatever class probably calls one or more private methods one of which eventually makes the service call. Do yo want to unnecessarily force that poor private method to mess with your service exception? Of course not. Let it propagate to the single handler that handles service exceptions - - for all your controllers/backed beans. Read below...

    Presentation Layer
    We're using JSF as the presentation technology. Managed/Backed beans that are doing calls to the Service methods can catch ServiceExceptions.
    I am not an expert on JSF at all, I haven't touched it in years, and I have never used it seriously. So I can't tell you how to do it specifically in JSF. But here's the generic approach that you can use with any presentation tier framework, such as Struts, Spring MVC, or, I'm sure, JSF. You can write an abstract front-end action class (call it controller, managed bean, whatever) that would implement the actual service execution method in the following way:

    Code:
    // your abstract action pseudo-code to invoke the view-specific service call...
    
    executeServiceMethod:
    {   
      try {
           doExecute(...); // call the abstract execute method that each specific action will implement to call the action specific business service API
      } catch (Throwable t) {
           // do your generic handling of any system errors that ocurred in servic tier
          logger.error(t);
          if (t instance of ContextAwareException) {
               logger.error(t.getContextinfo()); 
          }
          String msgKey = msgResolver.resolve(t); // call your PT resolver that maps exceptions to specific PT messages, if some exceptions require a specific message
           
           - place messageKey into request
           - return generic error view (that will display a msg using msgKey, or default message)
     }
    Make all your actions implement that abstract class and provide their versions of the "doExecute" method, or whatever you call it. In most cases, you should not implement any try/catch's in the action-specific "doExecute"s, However, for those use cases/actions that require you to do something different from displaying the error page - and only for those cases! - implement separate try/catch blocks in the related action implementations. If those cases are not based on the actions but on the types of the thrown exceptions, then simply insert the catches for those specific exceptions before the "catch Throwable" in your abstract action's code above. You should be all set in the front-end on the server side. Now, exceptions may still be thrown in your JSPs, in tags. To take care of those, put this filter into your web.xml:

    Code:
        <error-page>
            <exception-type>java.lang.Throwable</exception-type>
            <location>/WEB-INF/jsp/error.jsp</location>
        </error-page>
    Obviously, replace "/jsp/error.jsp" with your actual error page name and location. You are all set!

    And don't catch exceptions anywhere else. Your code will be completely error-proof and junk-free! (I mean error-handling junk; I can't speak for any other junk you might put in there. Try not to. ) And you won't lose any valuable error information whenever an exception is thrown. Isn't it beautiful? Compare this to the thousands of meaningless try/catchs and throws your project probably has now... Brrrr!

    HTH.
    Good luck!

  10. #20

    Default

    The problem is that JSF is a component based technology...so each button click can have a code piece behind that button which would be doButtonClick() which calls the service method. There's no generic request/response behavour but much more component based action/response behavour.

    So having one doExecute() method wouldnt really help here as different services might be called and not all in the doExecute method. But im not sure if i understood you correctly.

    Your idea would be to a have a CommonAbstractManagedBean that would have an abstract method doExecute(). My Concrete SearchManagedBean would then implement doExecute() and in different places in the managed bean, like in the doSearchButton() method i would call the doExecute() method. Was that correct?

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •