Не удается сопоставить параметры строки запроса с моим JavaBean (с помощью Spring 4 и Datatables)

Я действительно застрял в попытке сопоставить мои параметры QueryString с моим объектом Spring JavaBean Command, и до сих пор не смог найти ответ на свой вопрос.

Я использую плагин jQuery Datatables с обработкой на стороне сервера, чтобы каждое действие в моем datatable запускало AJAX-запрос к моему приложению Spring.

Вот параметры, которые плагин Datatable отправляет в мой сервис Rest:

http://localhost:8080/relatorios/produtos-source?draw=2&columns[0][data]=nome&columns[0][name]=&columns[0][searchable]=true&columns[0][orderable]=true&columns[0][search][value]=&columns[0][search][regex]=false&columns[1][data]=nomesAlternativos&columns[1][name]=&columns[1][searchable]=true&columns[1][orderable]=true&columns[1][search][value]=&columns[1][search][regex]=false&order[0][column]=2&order[0][dir]=asc&start=0&length=10&search[value]=ss&search[regex]=false&_=1400248561282

Вот как я получаю его в моем Spring Controller:

@RequestMapping(value = "/produtos-source", method = RequestMethod.GET)
@ResponseStatus(HttpStatus.OK)
@ResponseBody
public ProdutoTable dataTableRequest(@ModelAttribute DataTableCriterias criterias) {
    ...
}

И, наконец, это мой DataTableCriterias JavaBean (обозначается @ModelAttribute):

public class DataTableCriterias {
    private int draw;
    private int start;
    private int length;

    private Map<SearchCriterias, String> search;

    private List<Map<OrderCriterias, String>> order;

    private List<Column> columns;

    public enum SearchCriterias {
        value,
        regex
    }

    public enum OrderCriterias {
        column,
        dir
    }

    public class Column {
        private String data;
        private String name;
        private boolean searchable;
        private boolean orderable;
        private Map<SearchCriterias, String> search;
    }
}

(get / setters опущены)

Это почти идеально работает! Если я уберу эту строку:

private List<Column> columns;

затем Spring автоматически заполняет мой bean-компонент DataTableCriterias из строки запроса (но, конечно, я не сопоставляю свойство columns)

Но с этой добавленной строкой я получаю эту ошибку:

2014-05-16 17:20:16.605 ERROR 2368 --- [tomcat-http--99] o.a.c.c.C.[.[.[.[dispatcherServlet]      : Servlet.service() for servlet [dispatcherServlet] in context with path [/relatorios] threw exception [Request processing failed; nested exception is org.springframework.beans.InvalidPropertyException: Invalid property 'columns[0][data]' of bean class [com.bergermobile.rest.domain.DataTableCriterias]: Illegal attempt to get property 'columns' threw exception; nested exception is org.springframework.beans.NullValueInNestedPathException: Invalid property 'columns' of bean class [com.bergermobile.rest.domain.DataTableCriterias]: Could not instantiate property type [com.bergermobile.rest.domain.DataTableCriterias$Column] to auto-grow nested property path: java.lang.InstantiationException: com.bergermobile.rest.domain.DataTableCriterias$Column] with root cause

org.springframework.beans.NullValueInNestedPathException: Invalid property 'columns' of bean class [com.bergermobile.rest.domain.DataTableCriterias]: Could not instantiate property type [com.bergermobile.rest.domain.DataTableCriterias$Column] to auto-grow nested property path: java.lang.InstantiationException: com.bergermobile.rest.domain.DataTableCriterias$Column
    at org.springframework.beans.BeanWrapperImpl.newValue(BeanWrapperImpl.java:651)

На мой взгляд, главная проблема заключается в том, что параметр 'column', отправляемый плагином Datatable, является двумерным, а иногда и трехмерным массивом:

columns[0][data]=nome
columns[0][search][regex]=false

Итак, похоже, что мой Бин был прав, но я получаю эту ошибку, и теперь я застрял.

Есть идеи?

Большое спасибо!

3 ответа

Решение

Итак, я решил эту проблему, слегка изменив параметры, отправленные на сервер, чтобы преобразовать два трехмерных массива столбцов в двумерный массив. Так:

columns[0][search][value]=myvalue
columns[0][search][regex]=false

в конечном итоге был:

columns[0][searchValue]=myvalue
columns[0][searchRegex]=false

Вот как это сделать в Databables:

$('#produtosTable').DataTable({
    serverSide: true,
    ajax: {
        "url": "produtos-source",
        "data": function(data) {
            planify(data);  
        } 
    }
});

function planify(data) {
    for (var i = 0; i < data.columns.length; i++) {
        column = data.columns[i];
        column.searchRegex = column.search.regex;
        column.searchValue = column.search.value;
        delete(column.search);
    }
}

Таким образом, я могу получить эти свойства в моем объекте Model, используя это поле:

private List<Map<ColumnCriterias, String>> columns;

Просто для справки, вот мой контроллер:

@RequestMapping(value = "/produtos-source", method = RequestMethod.GET)
@ResponseStatus(HttpStatus.OK)
@ResponseBody
public ProdutoTable dataTableRequest(@ModelAttribute DataTableCriterias criterias) {
    ProdutoTable produtoTable = produtosService.findProdutos();
    produtoTable.setDraw(criterias.getDraw());
    return produtoTable;
}

и вот, наконец, мой DataTableCriterias @ModelAttriute:

public class DataTableCriterias {
    private int draw;
    private int start;
    private int length;

    private Map<SearchCriterias, String> search;

    private List<Map<ColumnCriterias, String>> columns;

    private List<Map<OrderCriterias, String>> order;

    public enum SearchCriterias {
        value,
        regex
    }
    public enum OrderCriterias {
        column,
        dir
    }
    public enum ColumnCriterias {
        data,
        name,
        searchable,
        orderable,
        searchValue,
        searchRegex
    }

(get / setters опущено)

Я знаю, что опоздал на вечеринку, но это: https://github.com/darrachequesne/spring-data-jpa-datatables

это прекрасная альтернатива для элегантного чтения ваших данных. Даже если вы не хотите использовать JPA, вы можете просто использовать классы DataTablesInput и DataTablesOutput для правильного чтения ввода. Я также включил jquery.spring-friendly.min.js, который позволил Spring легко читать входящие переменные.

Спасибо https://github.com/darrachequesne за хорошее элегантное решение.

Вы посылаете columns[0] как параметр, но columns не имеет записи с индексом 0. На самом деле она вообще не имеет записи, поскольку является нулевой.

Вы должны создать экземпляр списка в конструкторе DataTableCriterias для того, чтобы сделать эту работу. И в нем должно быть достаточно записей для параметров, которые вы отправляете.

Другие вопросы по тегам