Я получаю java.util.List<Object[]>
через JSON-rpc в качестве массива JavaScript следующим образом.
[
[1, 0.10, 1.00],
[2, 0.20, 2.00],
[3, 0.30, 3.00],
[4, 0.40, 4.00],
[5, 0.50, 5.00],
[6, 0.60, 6.00],
[7, 0.70, 7.00],
[8, 0.80, 8.00],
[9, 0.90, 9.00],
[10, 1.00, 10.00],
[11, 1.10, 11.00],
[12, 1.20, 12.00],
[13, 1.30, 13.00],
[14, 1.40, 14.00],
[15, 1.50, 15.00],
[16, 1.60, 16.00],
[17, 1.70, 17.00],
[18, 1.80, 18.00]
]
Мне нужно передать этот же массив на сервер (с небольшим изменением в последнем измерении).
Я использую следующую функцию для отправки этого массива.
var request;
var timeout;
var itemsArray=[];
function insert()
{
if(!request)
{
var i=0;
$('input[name="txtCharge[]"]').each(function()
{
isNaN($(this).val())||$(this).val()===''?itemsArray[i][2]='':itemsArray[i][2]=eval(eval($(this).val()).toFixed(2));
i++;
});
request = $.ajax({
dataType:"json",
type: "POST",
data: JSON.stringify({jsonrpc:'2.0', method:'insertZoneCharges', id:'jsonrpc', params:[itemsArray]}),
contentType: "application/json-rpc; charset=utf-8",
url: "AddZoneChargeList",
success: function(response)
{
alert(response.result);
},
complete: function()
{
timeout = request = null;
},
error: function(request, status, error)
{
if(status!=="timeout"&&status!=="abort")
{
alert(status+" : "+error);
}
}
});
timeout2 = setTimeout(function() {
if(request)
{
request.abort();
alert("The request has been timed out.");
}
}, 300000);
}
}
Структура массива itemsArray
после цикла точно такая же, как указано в первом фрагменте.
Метод, вызываемый этой функцией jQuery, выглядит следующим образом.
@Namespace("/admin_side")
@ResultPath("/WEB-INF/content")
@ParentPackage(value="json-default")
public final class ZoneCharge extends ActionSupport implements Serializable
{
private static final long serialVersionUID = 1L;
public ZoneCharge() {}
//This method is invoked by the given jQuery function.
//It should accept the array as a parameter of type List<Object[]> but it doesn't.
@SMDMethod
public String insertZoneCharges(@SMDMethodParameter(name="list")List<Object[]> list)
{
for(Object[]o:list)
{
System.out.println(o[0]+" : "+o[1]+" : "+o[2]);
}
return "The action completed successfully.";
}
@Action(value = "AddZoneChargeList",
results = {
@Result(name = ActionSupport.SUCCESS, type = "json", params = {"enableSMD", "true"})},
interceptorRefs = {
@InterceptorRef(value = "json", params = {"enableSMD", "true"})})
public String insertAction() throws Exception {
return ActionSupport.SUCCESS;
}
}
Когда делается попытка сделать запрос, он вызывает следующее исключение.
Feb 19, 2014 6:14:00 AM org.apache.struts2.json.rpc.RPCError error
SEVERE: Incompatible types for property insertZoneCharges
org.apache.struts2.json.JSONException: Incompatible types for property insertZoneCharges
at org.apache.struts2.json.JSONPopulator.convertToCollection(JSONPopulator.java:254)
at org.apache.struts2.json.JSONPopulator.convert(JSONPopulator.java:131)
at org.apache.struts2.json.JSONInterceptor.invoke(JSONInterceptor.java:242)
at org.apache.struts2.json.JSONInterceptor.intercept(JSONInterceptor.java:133)
at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:246)
at org.apache.struts2.impl.StrutsActionProxy.execute(StrutsActionProxy.java:54)
at org.apache.struts2.dispatcher.Dispatcher.serviceAction(Dispatcher.java:562)
at org.apache.struts2.dispatcher.ng.ExecuteOperations.executeAction(ExecuteOperations.java:77)
at org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter.doFilter(StrutsPrepareAndExecuteFilter.java:99)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:243)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
at filter.NoCacheFilter.doFilter(NoCacheFilter.java:25)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:243)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330)
at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.invoke(FilterSecurityInterceptor.java:118)
at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.doFilter(FilterSecurityInterceptor.java:84)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
at org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:113)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
at org.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.java:103)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
at org.springframework.security.web.authentication.AnonymousAuthenticationFilter.doFilter(AnonymousAuthenticationFilter.java:113)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
at org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter.doFilter(SecurityContextHolderAwareRequestFilter.java:154)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
at org.springframework.security.web.savedrequest.RequestCacheAwareFilter.doFilter(RequestCacheAwareFilter.java:45)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
at org.springframework.security.web.authentication.www.BasicAuthenticationFilter.doFilter(BasicAuthenticationFilter.java:150)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:199)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:110)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
at org.springframework.security.web.csrf.CsrfFilter.doFilterInternal(CsrfFilter.java:105)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:108)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
at org.springframework.security.web.header.HeaderWriterFilter.doFilterInternal(HeaderWriterFilter.java:57)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:108)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
at org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter.doFilterInternal(WebAsyncManagerIntegrationFilter.java:50)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:108)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
at org.springframework.security.web.session.ConcurrentSessionFilter.doFilter(ConcurrentSessionFilter.java:125)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:87)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
at org.springframework.security.web.access.channel.ChannelProcessingFilter.doFilter(ChannelProcessingFilter.java:144)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:192)
at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:160)
at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:344)
at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:261)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:243)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
at org.springframework.web.multipart.support.MultipartFilter.doFilterInternal(MultipartFilter.java:119)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:108)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:243)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:222)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:123)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:472)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:171)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:99)
at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:936)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:407)
at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1004)
at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:589)
at org.apache.tomcat.util.net.AprEndpoint$SocketProcessor.run(AprEndpoint.java:1822)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1110)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:603)
at java.lang.Thread.run(Thread.java:722)
Почему этот массив не отображается на List<Object[]>
, когда тот же List<Object[]>
правильно сопоставляется с массивом при получении ответа от сервера (это делается с помощью отдельной функции jQuery, которая не рассматривается в этом вопрос)?
РЕДАКТИРОВАТЬ 1:
Следующая строка,
data: JSON.stringify({jsonrpc:'2.0', method:'insertZoneCharges', id:'jsonrpc', params:[itemsArray]})
в данной функции jQuery соответствует следующей строке.
{
"jsonrpc": "2.0",
"method": "insertZoneCharges",
"id": "jsonrpc",
"params": [
[
[1, 0.1, 1],
[2, 0.2, 2],
[3, 0.3, 3],
[4, 0.4, 4],
[5, 0.5, 5],
[6, 0.6, 6],
[7, 0.7, 7],
[8, 0.8, 8],
[9, 0.9, 9],
[10, 1, 10],
[11, 1.1, 11],
[12, 1.2, 12],
[13, 1.3, 13],
[14, 1.4, 14],
[15, 1.5, 15],
[16, 1.6, 16],
[17, 1.7, 17],
[18, 1.8, 18]
]
]
}
Это выглядит корректно и должно корректно отображаться на java.util.List<Object[]>
, не вызывая исключения.
ИЗМЕНИТЬ 2:
Это работает, когда параметр типового типа удаляется, так что список просто List
(а не <List<Object[]>>
) или параметр имеет тип List<List<Object>>
. Что-то вроде,
@SMDMethod
public String insertZoneCharges(@SMDMethodParameter(name="list")List<List<Object>> list)
{
for(List<Object> o:list)
{
System.out.println(o);
}
return "The action completed successfully.";
}
Цикл отображает следующий вывод.
[1, 0.1, 1]
[2, 0.2, 2]
[3, 0.3, 3]
[4, 0.4, 4]
[5, 0.5, 5]
[6, 0.6, 6]
[7, 0.7, 7]
[8, 0.8, 8]
[9, 0.9, 9]
[10, 1, 10]
[11, 1.1, 11]
[12, 1.2, 12]
[13, 1.3, 13]
[14, 1.4, 14]
[15, 1.5, 15]
[16, 1.6, 16]
[17, 1.7, 17]
[18, 1.8, 18]
Глядя на вывод, массив JSON должен правильно отображаться на List<Object[]>
, но этого не происходит.
РЕДАКТИРОВАТЬ 3: (не существенное редактирование).
Хотя фактический массив невидим в заданной функции jQuery, это можно просто воспроизвести с помощью следующей функции jQuery.
function insert()
{
var a=[[1, 2], [3, 4]]; //Array.
$.ajax({
dataType:"json",
type: "POST",
data: JSON.stringify({jsonrpc:'2.0', method:'insertZoneCharges', id:'jsonrpc', params:[a]}),
contentType: "application/json-rpc; charset=utf-8",
url: "AddZoneChargeList",
success: function(response)
{
alert(response.result);
},
complete: function()
{
//Do something.
},
error: function(request, status, error)
{
//Do something.
}
});
}
}
И ожидаемый параметр метода метода SMD может быть либо java.util.List<Object[]>
, либо java.util.List<Long[]>
. В любом случае он не выполняется с предоставленным исключением.
Остается одна последняя вещь. Если существует один размерный массив, подобный (в JavaScript),
var a=[1, 2];
то это правильно отображается на Long[]
(и до Object[]
) в качестве параметра метода SMD.
Итак, теперь я больше не вижу, где искать.