简体   繁体   中英

Angularjs - Spring MVC Rest : how to handle exceptions

I am developping an single page app with angularjs and Spring Mcv Rest.
I am calling my service (mail sending with javax mail) like that in Angularjs : SendProformaFax.get({idCommande:$scope.commande.id})

And on server side my service :

@RequestMapping(value = "/sendProformaFax/{idCommande}",
            method = RequestMethod.GET,
            produces = MediaType.APPLICATION_JSON_VALUE)
    @Timed
    public void imprimeProforma(@PathVariable String idCommande) {
        Commande commande = commandeRepository.findOne(new Long(idCommande));
        List<Vente> ventes = venteRepository.findAllByCommande(commande);
        blService.sendProformaFax(ventes);
   }

I would like to display a message when the function sendProformaFax throws a MessagingException.

I don't know how to return this exception in my RestController and how to catch it in Angularjs.

If anyone can help me on this...
Thanks.

EDIT : On server side I am doing this :

@ExceptionHandler(value = Exception.class)
    public ErrorView defaultErrorHandler(HttpServletRequest req, Exception e) throws Exception {
        // If the exception is annotated with @ResponseStatus rethrow it and let
        // the framework handle it - like the OrderNotFoundException example
        // at the start of this post.
        // AnnotationUtils is a Spring Framework utility class.
        if (AnnotationUtils.findAnnotation(e.getClass(), ResponseStatus.class) != null)
            throw e;

        // Otherwise setup and send the user to a default error-view.
        ErrorView mav = new ErrorView();
        mav.setException(e.getMessage());
        mav.setUrl(req.getRequestURL().toString());
        mav.setMessage("Veuillez contacter le support informatique.");
        return mav;
    }

On Angularjs side I am doing this

CreateFichierCiel.get({params:param}, function (response) {
                $scope.infoMessage = "La génération du fichier CIEL est terminée."
                $activityIndicator.stopAnimating();
                $("#messageModal").modal('show');
                $scope.find();
            }, function (reason) {
                $("#errorModal").modal('show');
            }) 

But 'reason' object is like this :

config: Object data: Object error: "Internal Server Error" exception: "java.lang.NullPointerException" message: "No message available" path: "/api/createFichierCiel/15-00005" status: 500 timestamp: 1438430232307 proto: Object headers: function (name) { status: 500 statusText: "Internal Server Error" proto: Object

So I am not getting the ErrorView class sent from the server. If anyone can see where I am wrong here...

Thanks

You can make ExceptionHandler for MessagingException and set HTTPStatus to indicate that response has an error (egz. BAD_REQUEST )

@ExceptionHandler(MessagingException.class)
@ResponseStatus(HTTPStatus.BAD_REQUEST)
@ResponseBody
public ErrorView handleMessagingException(MessagingException ex) {
    // do something with exception and return view
}

In AngularJS you can catch it from resource service like this:

MessagingService.get({idCommande: 1}, function (data) {
// this is success
}, function (reason) {
// this is failure, you can check if this is a BAD_REQUEST and parse response from exception handler
};

It almost the same when you use $http .

Adding to the answer by kTT , starting with Spring 4 you can wrap your @ExceptionHandler method in a class annotated with @ControllerAdvice so that you will have the same message for the same type of exception across the whole application. More you can look here

That is how I did it, we are using spring mvc and angularjs in our project. I have this controllerAdvice class

@ControllerAdvice
public class ExceptionControllerAdvice {

@ExceptionHandler(ServiceException.class)
public ResponseEntity<ErrorResponse> rulesForCustomerNotFound(HttpServletRequest req, ServiceException e) 
{
    ErrorResponse error = new ErrorResponse();
    error.portalErrorCode = e.getExceptionCode(); 
    error.message = e.getMessage();
    return new ResponseEntity<ErrorResponse>(error, HttpStatus.NOT_FOUND);
    }
}

class ErrorResponse {
   public int portalErrorCode;
   public String message;
}

and then in restful controller where ServiceException is a customized runnable exception:

@Override
@RequestMapping("/getControls/{entity}")
public List<Control> getControls(@PathVariable(value="entity") String entity) throws ServiceException {
    List<Control> controls = ImmutableList.of();
     try {
        controls = dao.selectControls(entity);
    } catch (Exception e) {
        logger.error("getting list of controls encountered an error ", e);
        throw new ServiceException(50, "getting list of controls encountered an error.");
    }
     return controls;
}

in my app.js file in angularjs I use

.config(['$httpProvider', function ($httpProvider) {
$httpProvider.interceptors.push(function ($q, $location) {
    return {
        'response': function (response) {
            //Will only be called for HTTP up to 300
            return response;
        },
        'responseError': function (rejection) {
            if(rejection.status === 0) {
                alert('There is a problem connecting to the server. Is the server probably down?!');
            }
            else {
                $location.url('/error').search({rejection: rejection});
            }
            return $q.reject(rejection);
        }
    };
});
}])

and in a error.controller.js

function init() {       
    ctrl.rejection = $location.search().rejection; 
    ctrl.portalErrorCode = ctrl.rejection.data.portalErrorCode;
    ctrl.errorMessage = ctrl.rejection.data.message;
    $log.info('An error occured while trying to make an ajax call' + ctrl.errorMessage + ': ' + ctrl.portalErrorCode);
}

and of course in error.tpl.html

            <h2>
               {{ctrl.rejection.status}} {{ctrl.rejection.statusText}}
            </h2>
            <h3 class="error-details">
                Sorry, an error has occurred!
            </h3>
            <h3 class="error-details">
                {{ctrl.errorMessage}}
            </h3>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM