Не удается сопоставить параметры строки запроса с моим 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
для того, чтобы сделать эту работу. И в нем должно быть достаточно записей для параметров, которые вы отправляете.