Spring MVC and Ajax

1

I'm developing a web app in java using the Spring MVC framework. However, a part of the project has broken out!

First I'll show the print on the screen to make it easier to understand.

Image:

WhatIwanttodois:whentheuserselectsthecompany,theelementsbelow(salary,13thsalaryandIncomeReport)willbeloadeddynamically.Notallcompanieshavealltheoptions.Obs:Thatbuttongeneratedemowouldnotexistanymore.

AftersomeresearchIthoughtaboutdoingthis:

  • Createajavascriptfunctiontograbtheselectactionandsendtheselecteditemviaajax.AsfarasIunderstand,Icanuseannotation@RequestBodytoreadthejsonsentbyajax.

  • Withtheselectediteminhand,IcanpassitasaparameterintheselectImakeinthebankthatbringstheoptionsavailabletothatcompany.

  • Withannotation@ResponseBodyIsendajsonwiththeoptionsandcreatethetagswithjavascript.

Idonotknowiflogicisright,buttheproblemwithitallisthatIdonotknowhowtodoit.

Myquestions:

  • HowdoIretrievetheselecteditemandsendittothespringcontroller?Forexample:IhaveacompanyobjectthathasthenameandCNPJattributes,howdoIgettheCNPJattributeoftheselecteditemandsendtocontroller?

  • ThenhowdoIreturntheitemsavailableforthatcompanytothepage?

Seehowmycontrollermethodis:

@RequestMapping(value="/", method = RequestMethod.GET)
public String index(Model model, 
                    @ModelAttribute("usuarioLogado") Usuario usuario,
                    Empresa empresa) {

    Funcionario funcionario = daoFuncionario.getFuncionario(usuario);
    List<Empresa> empresas = daoEmpresa.listaEmpresas(funcionario);

    model.addAttribute("empresa", empresa);
    model.addAttribute("funcionario", funcionario);
    model.addAttribute("empresas", empresas);

    return "usuario/menu";
}

Now the page:

<form:form commandName="empresa" class="form-horizontal">
    <fieldset>
        <legend>Olá, ${funcionario.nome}</legend>

        <!-- Select Empresa -->
        <div class="form-group">
            <label for="empresa">Empresa </label>

            <!-- 
            <select class="form-control">
                <c:forEach items="${empresas}" var="empresa">
                    <option value="${empresa.cnpj}">
                        ${empresa.cnpjFormatado}- ${empresa.razaoSocial}
                    </option>
                </c:forEach>
            </select>
             -->

            <form:select path="razaoSocial" class="form-control">
                <form:options items="${empresas}" />
            </form:select>

I also do not know how to select. From the first form using c:forEach or using the spring select itself.

EDIT

Personally, I'm getting the item selected in the controller like this:

$(document).ready(function() {

    function empresaSelecionaClick() {
        var cnpj = $("#razaoSocial option:selected" ).val();
        var json = {cnpj : cnpj}

        $.ajax({
            type: 'POST',
            url: 'menuDinamico',
            contentType: 'application/json',
            data: JSON.stringify(json),

            success : function(resposta){
                // pegar a lista e montar os elementos
            }
        })

        .done(function() {
            console.log("success");
        })
        .fail(function() {
            console.log("error");
        });
    }

    $("#razaoSocial").change(empresaSelecionaClick);

});

No controller methods:

@RequestMapping(value = "/menu", method = RequestMethod.GET)
public @ResponseBody ModelAndView menu(@ModelAttribute("usuarioLogado") Usuario usuario, Empresa empresa) {
    ModelAndView mav = new ModelAndView("usuario/menu");

    Funcionario funcionario = daoFuncionario.getFuncionario(usuario);
    mav.addObject("funcionario", funcionario);
    mav.addObject("empresa", empresa);
    mav.addObject("empresas", daoEmpresa.listaEmpresas(funcionario));

    return mav;

}

@RequestMapping(value = "/menuDinamico", method = RequestMethod.POST)
private @ResponseBody List<UltimoPeriodoAberto> listaOpcoes(@RequestBody Empresa empresa) {

    List<UltimoPeriodoAberto> opcoes = daoUltimoPeriodoAberto.getPeriodoHolerite(empresa);

    System.out.println("CNPJ empresa: " + empresa.getCnpj());

    for (UltimoPeriodoAberto ultimoPeriodoAberto : opcoes) {
        System.out.println(ultimoPeriodoAberto.getDescricao());
    }

    return opcoes;
}

However in the second method you are giving null pointer execption in the line:

List<UltimoPeriodoAberto> opcoes = daoUltimoPeriodoAberto.getPeriodoHolerite(empresa);

I can not identify the error.

EDIT

Well, I got it sorted out. I did so

I changed the annotation @RequestBody to @ModelAttribute :

    @RequestMapping(value = "/menuDinamico", method = RequestMethod.POST)
public @ResponseBody List<UltimoPeriodoAberto> opcoesDinamicas(@ModelAttribute("empresa") Empresa empresa) {

    System.out.println(empresa.getCnpj());
    List<UltimoPeriodoAberto> opcoes = daoUltimoPeriodoAberto.getPeriodoHolerite(empresa);

    System.out.println(opcoes.size());

    return opcoes;
}

I changed the ajax request too ..

$(document).ready(function() {
    function empresaSelecionaClick() {
        var empresa = $(this).serialize();

        $.ajax({
            type: 'POST',
            url: 'menuDinamico',
            data: empresa,
        })

        .done(function(data) {
            console.log("success");
            console.log(data)
        })
        .fail(function() {
            console.log("error");
        });
    }
    $("#cnpj").change(empresaSelecionaClick);
});

Now I'm getting the error 406 in ajax:

  

The resource identified by this request is only capable of generating responses not acceptable according to the request "accept" headers

Ajax can not get my list, does anyone have any suggestions?

    
asked by anonymous 29.05.2015 / 15:50

2 answers

1

In the way that you intend to use, and I understand, you do not have to use @ModelAttribute , since we will not send the whole object of the template that is in the form.

As we will only pass the CNPJ as a query parameter, I will consider two examples:

  • receiving the CNPJ in the request body, such as JSON, in {"cnpj": "11111111111"} format. The service for consultation will answer in /empresa/menudinamico
  • receiving the CNPJ as the URL parameter, with the URL the default ''

In the above scenarios, both return JSON as a response and this is my test HTML:

<select id="razaoSocial">
  <option value="0">--- Selecione</option>
  <option value="11111111111">Empresa 1</option>
  <option value="22222222222">Empresa 2</option>
</select>

<div id="options"></div>

OK, I made this introduction, first I'll show you how the controller was. For the first case we will have this (note that it is summarized):

@ResponseBody
@RequestMapping(value = "/menudinamico",
    method = {GET, POST},
    consumes = APPLICATION_JSON,
    produces = APPLICATION_JSON)
public final List<UltimoPeriodoAberto> optionByRequestBody(@RequestBody final Empresa empresa) {
    LOGGER.info("CNPJ recebido: " + empresa.getCnpj());
    return this.daoUltimoPeriodoAberto.getPeriodoHolerite(empresa);
}

As we are passing a JSON in the body of the message we need to talk to the spring this, ie with this it will get the JSON and deserialize to the object.

And for the second, your method should look like this:

@ResponseBody
@RequestMapping(value = "/menudinamico/{cnpj}", method = GET, produces = APPLICATION_JSON)
public final List<UltimoPeriodoAberto> optionByRequestParam(@PathVariable final String cnpj) {
    LOGGER.info("CNPJ recebido: " + cnpj);
    return this.daoUltimoPeriodoAberto.getPeriodoHolerite(new Empresa(cnpj));
}

In this case, different from the first, we are using @PathVariable ", which is to tell the string "inject" the value according to the template of the given URL. Also removed @RequestBody since we are not sent anything in the body of the message now, but only as a parameter in the URL.

In both cases we use @ResponseBody , that is, we are talking about spring serializing the return as defined in produces and according to Accept sent by the client as well. You can see about this in detail in the reference documentation.

For the call, I'll consider this excerpt that you said is already OK to retrieve the select value of the form, changing only the body of them:

$(document).ready(function() {
    function empresaSelecionaClick() {
        var cnpj = $(this).val();
        var json = {cnpj: cnpj};

        // substitua aqui conforme necessário

    }

    $("#razaoSocial").change(empresaSelecionaClick);
});

This for the first method:

$.ajax({
    type: 'POST',
    url: '/menudinamico',
    contentType: 'application/json',
    data: JSON.stringify(json),
    success : function(data){
        innerOptionsInHTML(data);
    }
}).done(function() {
    console.log("success");
}).fail(function() {
    console.log("error");
});

This for the second method:

$.ajax({
    type: 'GET',
    url: '/menudinamico/' + cnpj,
    success : function(data){
        innerOptionsInHTML(data);
    }
}).done(function() {
    console.log("success");
}).fail(function() {
    console.log("error");
});

I used CNPJ 11111111111 for the first method, which returned this to me:

[
   {
      "id":1,
      "nome":"Option 1"
   },
   {
      "id":2,
      "nome":"Option 2"
   }
]

And the CNPJ 22222222222 for the second method, which returns this:

[
   {
      "id":3,
      "nome":"Option 3"
   },
   {
      "id":4,
      "nome":"Option 3"
   },
   {
      "id":5,
      "nome":"Option 5"
   }
]

To generate the content in your HTML, you can do something like this:

function innerOptionsInHTML(data) {
    var json = JSON.parse(data);
    var options = $("#options");
    $(options).empty();
    $.each(json, function(i, item) {
        var obj = json[i];
        $(options).append("<li id=" + obj.id + ">" + obj.nome + "</li");
    });
};

After executing the first method, it generated this part in the HTML for the first case (the second is similar):

<ul id="options">
    <li id="1">Option 1</li>
    <li id="2">Option 2</li>
</ul>

Note : How are you using ModelAndView ", it is important to generate the options inside the form and with name / id of the object, so that Spring can "inject" it correctly.

Note 2 : I'm considering that your environment is Spring-configured properly.

    
10.06.2015 / 01:03
0

I would do it as follows:

A AJAX call with event .change(); That is, every time an item is selected within my select it would be passed the company name or id of the same to my controller , so you could perform the logic in your action by returning the relevant values and then putting them on the screen with jQuery .

Example:

<form:select id="razao-social" path="razaoSocial" class="form-control">
        <form:options items="${empresas}" />
</form:select>

$('#razao-social').change(function() {
    $.get("action/fazalgumaCoisa", {parametro: $(this).val()}, function(data) {
        //Criar a montagem da tela com o jQuery
    }).fail(function() {
        alert("Ocorreu um erro, tente novamente mais tarde.");
    });
});


    @RequestMapping(value = "action/faz-alguma-coisa", method=RequestMethod.GET)
    public @ResponseBody Object retornaAlgo(Model model, 
                    @ModelAttribute("usuarioLogado") Usuario usuario,
                    Empresa empresa, @RequestParam Long parametro){
   model.addAttribute("empresa", empresa);
    model.addAttribute("funcionario", funcionario);
    model.addAttribute("empresas", empresas);
        return Object;      
    }

In your case you should return something to be handled with Ajax callback .

    
01.06.2015 / 23:50