Search code examples
springjspspring-mvc

Can a Spring MVC controller method return something like a JSON object (containing a list of validation errors) instead a view?


I am pretty new in Spring MVC and I have the following problem.

I have a JSP view in which the user can upload a file, this view is a modal window (but it is not so important, it works fine):

<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt"%>

<!-- MODALE DI CONFERMA VALIDAZIONE PROGETTI -->
<div id="uploadFileRendicontoModal" class="modal fade">
    <div class="modal-dialog">
        <div class="modal-content">
            <div class="modal-header">
                <button type="button" class="close" data-dismiss="modal" aria-label="Close">
                    <span aria-hidden="true">&times;</span>
                </button>
                <h3 class="modal-title" style="color: #3b5a76;">Inserimento documento di rendicontazione per il progetto <b><c:out value="${progetto.codMecIniPro}" />-<c:out value="${progetto.twp1010Tipoprogetto.desTipPrg}" /></b> </h3>
                
            </div>
            <div id="modal-body" class="modal-body">
                
                <div class="well">
                    <div class="row" style="margin-top: 5%;">
                    
                        <div class="col-md-6">
                            <h4 style="margin-top: 2%; padding-left: 3%;">Allega rendiconto:</h4>
                        </div>
                    
                        <div class="col-md-6" style="padding-right: 5%;">
                            
                            <input id="rendicontoAllegato" class="form-control" style="height: 30px; padding: 0px;" type="file">
                                
                            <!--  <input type="file" id="fileProspetto" type="text"    class="rightAlligned"   onchange="if ($('#fileProspetto').val()!=''){$('#inoltra').removeAttr('disabled');$('#inoltra').removeClass('button-disabled');} else{$('#inoltra').prop('disabled',true);$('#inoltra').addClass('button-disabled');}" ></input>-->
                            
                        </div>
                        
                    </div>
                    
                    <div class="row" style="margin-top: 5%;">
                        <div class="col-md-6">
                            <h4 style="margin-top: 2%; padding-left: 3%;">Rendiconto allegato:</h4>
                        </div>
                        
                        <div class="col-md-6">
                            <p id="fileName" style="font-size: 15px;"></p>
                        </div>
                    
                    </div>
                </div>
                

            </div>

            <div class="modal-footer">
                <button id="chiudiAllegaRendicontoButton" type="button" class="btn btn-default"
                    data-dismiss="modal">Chiudi</button>
                <button id="confermaUploadRendicontoButton" type="button"
                    class="btn btn-primary" onclick="allegaRendiconto()" disabled>Allega</button>
            </div>
        </div>
        <!-- /.modal-content -->
    </div>
    <!-- /.modal-dialog -->
</div>
<!-- /.modal -->

<script type="text/javascript">
    $(document).ready(function() {
        //alert("DOCUMENT READY");
        
        $("#rendicontoAllegato").change(function() {
            $('#confermaUploadRendicontoButton').prop("disabled", false);   // Abilita il bottone per poter inviare il rendiconto
            
            var fileName = $("#rendicontoAllegato").val(); 
            $("#fileName").text(fileName);
        });
     });
</script>

So when the user click on the Allega button (in English means "Attach") it is performed this JavaScript function defined into an external .js file that simply retrieve the file inserted into the previous view input tag having type="file" and id="rendicontoAllegato" and perform an AJAX POST Request toward the inoltraRendiconto resource sending the previous file into a SourceData JSON object:

function allegaRendiconto()  {

    var fd = new FormData();
    
    fd.append('fileRendiconto',$('#rendicontoAllegato')[0].files[0]);
    
    $.ajax({
        type : "POST",
        url : "inoltraRendiconto",
        data: fd,
        processData: false,
        contentType: false
    }).done(function(principal) {
        document.open();
        document.write(principal);
        document.close();
    }).error(function(error) {
        showErrorMessage("errore");
    });;
    
}

Also this function works fine so this is the controller method that handle the previous POST request toward the inoltraRendiconto resource:

@RequestMapping(value = "/inoltraRendiconto", method = RequestMethod.POST)
public String inoltraRendiconto( HttpServletRequest request, Model model, Locale locale ) throws Exception {
    
    System.out.println("INTO inoltraRendiconto");
    
    DefaultMultipartHttpServletRequest multipartRequest = (DefaultMultipartHttpServletRequest) request;
    
    List<String> errors = validaInputDocumentoAllegato(multipartRequest.getFileMap().get("fileRendiconto"));
    
    return "blabla";   // THIS IS NOT GOOD !!!
}

So in this method I first retrieve the attached file (it works fine) and I pass it to the validaInputDocumentoAllegato() method that perform a validation (the method simply check if the file extension is valid and if the weight is less then a maximum size established). This validaInputDocumentoAllegato() method return a list of String representing validation errors (in this case something like "File extension is not valid" and "The file weight is too big").

I want to come back this error list to the previous view to show these error into it (if the file that the user is trying to upload is not valid it is not uploaded and the errors messages have to be shown in the same view).

As you can see this controller method return a String that represent a Spring MVC view but I don't have to do in this way.

Can I return something different (maybe a JSON object?) that contain the validation errors list that have to be shown in the opened view?


Solution

  • Try this add @ResponseBody annotation and return your error list:

    @RequestMapping(value = "/inoltraRendiconto", method = RequestMethod.POST)
    public @ResponseBody List<String> inoltraRendiconto( HttpServletRequest request, Model model, Locale locale ) throws Exception {
    
    System.out.println("INTO inoltraRendiconto");
    
    DefaultMultipartHttpServletRequest multipartRequest = (DefaultMultipartHttpServletRequest) request;
    
    List<String> errors = validaInputDocumentoAllegato(multipartRequest.getFileMap().get("fileRendiconto"));
    
    return errors;
    

    }