Исключение привязки даты весны Jqgrid - PullRequest
1 голос
/ 09 декабря 2010

ОС: Windows Vista, Framework: Jqgrid (последняя версия), Spring (последняя версия), JQuery (последняя версия) Я использую Jqgrid для отправки формы в Spring Controller для сохранения. Когда контроллер Spring пытается автоматически связать параметры запроса с объектом домена, он выдает исключение при попытке связать тип данных «Дата». Я использую формат JSon для передачи данных. Jqgrid отображает дату правильно. Строка передачи содержит '& -quot;' символы до и после даты, которая вызывает исключение. Я не знаю, как удалить escape-символ из Jqgrid. Я не знаю, как перехватить строку, прежде чем Spring получит возможность автоматического связывания. Заранее спасибо за помощь.

    public class JsonDateSerializer extends JsonSerializer<Date> {
private static final SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); 
AtOverride
public void serialize(Date date, JsonGenerator gen, SerializerProvider provider)
        throws IOException, JsonProcessingException {
    String formattedDate = dateFormat.format(date);
    gen.writeString(formattedDate);
}

}

Мой класс контроллеров имеет метод initBinder.

        @InitBinder
public void initBinder(WebDataBinder binder) {
    SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    dateFormat.setLenient(false);
    binder.registerCustomEditor(Date.class, new CustomDateEditor(dateFormat, false));
    binder.registerCustomEditor(String.class, new StringTrimmerEditor(true));
}

Exception stack trace
nested exception is org.springframework.core.convert.ConversionFailedException: Unable to convert value &quot;2010-12-01 11:10:00&quot; from type 'java.lang.String' to type 'java.util.Date'; nested exception is java.lang.IllegalArgumentException]
org.springframework.web.bind.annotation.support.HandlerMethodInvoker.doBind(HandlerMethodInvoker.java:820)
org.springframework.web.bind.annotation.support.HandlerMethodInvoker.resolveHandlerArguments(HandlerMethodInvoker.java:359)

Ответы [ 5 ]

1 голос
/ 11 декабря 2010

Я постараюсь настроить учебник в своем блоге, если у меня будет время сегодня.

Мой файл JSP - это простой файл JSP с типичным объявлением JqGrid:

<script type="text/javascript">
jq(function() {
    // This is the grid
    jq("#grid").jqGrid({
        url:'/myapp/users',
        datatype: 'json',
        mtype: 'GET',
        colNames:['Id','Username','First Name'],
        colModel:[
            {name:'id',index:'id', width:55,editable:false,editoptions:{readonly:true,size:10},hidden:true},
            {name:'firstName',index:'firstName', width:100,editable:true, editrules:{required:true}, editoptions:{size:10}, editrules:{required:true}},
            {name:'lastName',index:'lastName', width:80, align:"right",editable:true, editrules:{required:true}, editoptions:{size:10}, editrules:{required:true}}
        ],
        postData: { 
            // Here you can post extra parameters
            // For example using JQuery you can retrieve values of other css elements
        },
        rowNum:10,
        rowList:[10,20,30],
        height: 200,
        autowidth: true,
        rownumbers: true,
        pager: '#pager',
        sortname: 'id',
        viewrecords: true,
        sortorder: "asc",
        caption:"Users",
        emptyrecords: "Empty records",
        loadonce: false,
        loadComplete: function() {
            // Here you can provide extra functions after the grid is loaded completely
            // Like auto-height function
        },
        jsonReader : {
            root: "rows",
            page: "page",
            total: "total",
            records: "records",
            repeatitems: false, 
            cell: "cell",
            id: "id"
        }
    });

    // This is the pager
    jq("#grid").jqGrid('navGrid','#pager',
            {edit:false,add:false,del:false,search:true},
            { },
            { },
            { }, 
            { 
                sopt:['eq', 'ne', 'lt', 'gt', 'cn', 'bw', 'ew'],
                closeOnEscape: true, 
                    multipleSearch: true, 
                    closeAfterSearch: true }
    );

    // Custom Add button on the pager
    jq("#grid").navButtonAdd('#pager',
            {   caption:"Add", 
                buttonicon:"ui-icon-plus", 
                onClickButton: addRow,
                position: "last", 
                title:"", 
                cursor: "pointer"
            } 
    );

    // Custom Edit button on the pager
    jq("#grid").navButtonAdd('#pager',
            {   caption:"Edit", 
                buttonicon:"ui-icon-pencil", 
                onClickButton: editRow,
                position: "last", 
                title:"", 
                cursor: "pointer"
            } 
    );

    // Custom Delete button on the pager
    jq("#grid").navButtonAdd('#pager',
        {   caption:"Delete", 
            buttonicon:"ui-icon-trash", 
            onClickButton: deleteRow,
            position: "last", 
            title:"", 
            cursor: "pointer"
        } 
    );


    // Toolbar Search
    jq("#grid").jqGrid('filterToolbar',{stringResult: true,searchOnEnter : true, defaultSearch:"cn"});

});

Обратите внимание, я здесь использую метод noConflict JQuery. Так как у меня есть другая инфраструктура Javascript, которая использует $ , я заставил JQuery использовать для себя другой идентификатор. Я выбрал JQ и вот объявление:

<script type="text/javascript">
    var jq = jQuery.noConflict();
</script>

Javascript выше может быть объявлено в разделе заголовка вашего JSP. Важнейшей частью объявления JqGrid является jsonReader и тип данных . Убедитесь, что имя colModel соответствует свойствам вашей модели.

0 голосов
/ 11 декабря 2010

Для контроллера вот сопоставление с запросом / myapp / users / add:

@Controller
@RequestMapping("/myapp/users")
public class UserController {

    @RequestMapping(value = "/add", method = RequestMethod.POST)
    public @ResponseBody JsonGenericResponse addAsJson(
           @RequestParam("id") String id,
           @RequestParam("firstName") String firstName,
           @RequestParam("lastName") String lastName
    ) {

            // Validate input

            // Process data. Call a service, etc.

            // Send back a response
            // JsonGenericResponse is a custom  POJO 
            // Jackson will automatically serialize/deserialize this POJO to a JSON
            // The @ResponseBody annotation triggers this behavior

            JsonGenericResponse response = new JsonGenericResponse();
            response.setSuccess(false);
            response.setMessage("Error in server");

            return response;
    }
}

Вот JsonGenericResponse:

public class JsonGenericResponse {

private Boolean success;
private List<String> message;

public JsonGenericResponse() {
    message = new ArrayList<String>();
}

public Boolean getSuccess() {
    return success;
}

public void setSuccess(Boolean success) {
    this.success = success;
}

public List<String> getMessage() {
    return message;
}

public void setMessage(String message) {
    this.message.add(message);
}

}

Это просто простой POJO.

В вашем JSP для обработки ответа вы используете JavaScript в своем JqGrid. Ответ будет отправлен обратно тому, кто звонил (форма добавления в этом случае). Вот пример JavaScript, который будет обрабатывать ответ:

                if (result.success == false) {
                    for (var i = 0; i < result.message.length; i++) {
                        errors +=  result.message[i] + "<br/>";
                    }
                }  else {
                    jq("#dialog").text('Entry has been edited successfully');
                    jq("#dialog").dialog( 
                            {   title: 'Success',
                                modal: true,
                                buttons: {"Ok": function()  {
                                    jq(this).dialog("close");} 
                                }
                            });
                }

                return [result.success, errors, null];
0 голосов
/ 11 декабря 2010

Теперь, для сериализации / десериализации Джексона, вы удивитесь, насколько это просто.

Во-первых, убедитесь, что в вашем классе есть последняя библиотека Джексона. Затем откройте конфигурацию Spring xml и добавьте следующее:

<mvc:annotation-driven/> 

Вот и все:)

Убедитесь, что у вас установлены последние банки зависимостей. Я использую Spring 3.0.4. Там уже 3.0.5. Также убедитесь, что у вас установлена ​​последняя версия aspectjweaver.jar. Если вы хотите знать, что находится внутри этого тега, управляемого mvc-annotation, просто поищите в Интернете, и вы увидите, что он содержит. По сути, он автоматически объявляет HTTPMessageConverter для JSON и по умолчанию использует Джексона.

0 голосов
/ 11 декабря 2010

Если вы заметили на моем JSP, я добавил пользовательские кнопки. onClickButton вызывает другую функцию Javascript. Например, на кнопке Add у меня есть функция addRow. Вот объявление функции:

function addRow() {

    // Get the currently selected row
    jq("#grid").jqGrid('editGridRow','new',
            {   url: "/myapp/users/add", 
                    editData: {
                    // Here you add extra post parameters
                },
                recreateForm: true,
                beforeShowForm: function(form) {
                    // Here you can add, disable, hide elements from the popup form
                 },
                closeAfterAdd: true,
                reloadAfterSubmit:false,
                afterSubmit : function(response, postdata) 
                { 
                    // This is a callback function that will evaluate the response sent by your Controller
                    var result = eval('(' + response.responseText + ')');
                    var errors = "";

                    if (result.success == false) {
                        // Do whatever you like if not successful
                    }  else {
                        // Do whatever you like if  successful
                    }

                    // only used for adding new records
                    var new_id = null;

                    // Then this will be returned back to the popup form
                    return [result.success, errors, new_id];
                }
            });

}

Обратите внимание на URL:

url: "/myapp/users/add"

Это отображение на ваш контроллер, который обрабатывает запрос на добавление

0 голосов
/ 09 декабря 2010

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

StringTrimmerEditor(String charsToDelete, boolean emptyAsNull) 

На основе документов Spring:

charsToDelete - набор символов для удаления, кроме тогообрезать входную строку.Полезно для удаления нежелательных разрывов строк.Например, "\ r \ n \ f" удалит все новые строки и переводы строк в строке.

Я также использую последнюю версию JqGrid и Spring 3, но способ, которым я обрабатывал параметры, кажетсябыть проще.Вот как я это сделал:

@Controller
@RequestMapping("/json")
public class JsonController {

        @RequestMapping(method = RequestMethod.GET)
        public @ResponseBody JsonResponse getAll(
                @RequestParam("_search") String search,
                @RequestParam(value="filters", required=false) String filters,
                @RequestParam(value="datefrom", required=false) String datefrom,
                @RequestParam(value="dateto", required=false) String dateto,
                @RequestParam(value="page", required=false) String page,
                @RequestParam(value="rows", required=false) String rows,
                @RequestParam(value="sidx", required=false) String sidx,
                @RequestParam(value="sord", required=false) String sord
        ) { ... }

Все параметры передаются как обычные строки. datefrom и dateto являются пользовательскими параметрами, которые я передал из JqGrid.Дата берется из DatePicker JQuery и передается через JDGrid postData:

postData: { 
            datefrom: function() { return jq("#datepicker_from").datepicker("getDate"); },
            dateto: function() { return jq("#datepicker_to").datepicker("getDate"); }
        },

JsonResponse - это простой POJO, который я использовал для отображения параметров поиска, передаваемых JqGrid:

public class JsonResponse {

/**
 * Current page of the query
 */
private String page;

/**
 * Total pages for the query
 */
private String total;

/**
 * Total number of records for the query
 */
private String records;

/**
 * An array that contains the actual data
 */
private List<MyDTO> rows;

public JsonResponse() {
}

public String getPage() {
    return page;
}

public void setPage(String page) {
    this.page = page;
}

public String getTotal() {
    return total;
}

public void setTotal(String total) {
    this.total = total;
}

public String getRecords() {
    return records;
}

public void setRecords(String records) {
    this.records = records;
}

public List<MyDTO> getRows() {
    return rows;
}

public void setRows(List<MyDTO> rows) {
    this.rows = rows;
}

}

MyDTO также является простым объектом DTO.

В моем приложении SpringConContext.xml я просто должен объявить следующее:

<mvc:annotation-driven/>

И добавил банку Джексона для преобразования из JSON в POJO и наоборот

Чтобы преобразовать строковую дату в настоящую, я использовал большую библиотеку Joda.Но, конечно, вы можете использовать стандартную дату JDK.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...