edu.harvard.med.screensaver.ui.arch.view.aspects.UICommandExceptionHandlerAspect.java Source code

Java tutorial

Introduction

Here is the source code for edu.harvard.med.screensaver.ui.arch.view.aspects.UICommandExceptionHandlerAspect.java

Source

// $HeadURL$
// $Id$
//
// Copyright  2006, 2010, 2011, 2012 by the President and Fellows of Harvard College.
//
// Screensaver is an open-source project developed by the ICCB-L and NSRB labs
// at Harvard Medical School. This software is distributed under the terms of
// the GNU General Public License.

package edu.harvard.med.screensaver.ui.arch.view.aspects;

import javax.persistence.OptimisticLockException;

import org.apache.log4j.Logger;
import org.aspectj.lang.ProceedingJoinPoint;
import org.springframework.core.Ordered;
import org.springframework.dao.ConcurrencyFailureException;
import org.springframework.dao.DataAccessException;

import edu.harvard.med.screensaver.ScreensaverConstants;
import edu.harvard.med.screensaver.model.BusinessRuleViolationException;
import edu.harvard.med.screensaver.model.DataModelViolationException;
import edu.harvard.med.screensaver.service.OperationRestrictedException;
import edu.harvard.med.screensaver.ui.arch.util.Messages;
import edu.harvard.med.screensaver.ui.arch.view.AbstractBackingBean;
import edu.harvard.med.screensaver.ui.arch.view.EditableEntityViewer;

/**
 * Handles exceptions thrown by methods that are annotated
 * with {@link UICommand} by displaying an appropriate user error
 * message and then reloads the view with fresh data.
 */
public class UICommandExceptionHandlerAspect extends OrderedAspect implements Ordered {
    private static Logger log = Logger.getLogger(UICommandExceptionHandlerAspect.class);

    private Messages _messages;

    public void setMessages(Messages messages) {
        _messages = messages;
    }

    public Object invoke(ProceedingJoinPoint joinPoint) throws Throwable {
        try {
            return joinPoint.proceed();
        } catch (OperationRestrictedException e) {
            return handleException(joinPoint, e, "restrictedOperation", e.getMessage());
        }
        // catch the JPA exception for concurrency-related failures, since this is (apparently) what's being thrown, rather than the expected Spring-translated ConcurrencyFailureException
        // TODO: figure out why Spring-translated exceptions are not always/ever being thrown  
        catch (OptimisticLockException e) {
            return handleException(joinPoint, e, "concurrentModificationConflict", null);
        }
        // catch the Spring-translated exception for concurrency-related failures
        catch (ConcurrencyFailureException e) {
            return handleException(joinPoint, e, "concurrentModificationConflict", null);
        }
        // catch the top-most (i.e., most general) Spring-translated exception for persistence-related failures
        catch (DataAccessException e) {
            return handleException(joinPoint, e, "databaseOperationFailed", e.getMessage());
        } catch (BusinessRuleViolationException e) {
            return handleException(joinPoint, e, "businessError", e.getMessage());
        } catch (DataModelViolationException e) {
            return handleException(joinPoint, e, "businessError", e.getMessage());
        } catch (Throwable e) {
            log.error("", e);
            return handleException(joinPoint, e, "systemError", e.getMessage());
        }
    }

    private Object handleException(ProceedingJoinPoint joinPoint, Throwable t, String errorMessageId,
            String errorMessageArg) {
        AbstractBackingBean backingBean = (AbstractBackingBean) joinPoint.getTarget();
        log.error("backing bean " + backingBean.getClass().getSimpleName() + " method "
                + joinPoint.getSignature().getName() + " threw " + t.getClass().getSimpleName() + ": "
                + t.getMessage(), t);
        _messages.setFacesMessageForComponent(errorMessageId, null, errorMessageArg);
        if (backingBean instanceof EditableEntityViewer) {
            // TODO not working...
            // ((EntityViewer) backingBean).reload();
            // this is the best we can do with the current design
            EditableEntityViewer editableViewer = (EditableEntityViewer) backingBean;
            return editableViewer.cancel();
        }
        return ScreensaverConstants.REDISPLAY_PAGE_ACTION_RESULT;
    }
}