ArrayList 无法转换为 org.springframework.batch.core.JobParameter

ArrayList cannot be cast to org.springframework.batch.core.JobParameter

我想从 rest 客户端发送一个列表到 rest web 服务,它将在 Spring 批处理中启动一个作业。这是可能的还是我必须在开始工作之前将列表保存在 database/flatfile 中并从 database/flatfile 中读取输入值?我想有人在某些 Jira 问题中指出了如何做(见下文),但我至少无法弄清楚如何前进的基本想法。我放在我的控制器下面,以及我如何尝试将它投射到 JobParameter。我放置了 Jira link 和可能的方向,也许我应该采取但我真的不理解这个 Jira 问题中的建议。我在 SoapUi 客户端下方添加,最后我将整个错误日志粘贴在底部。

我的控制器:

@RequestMapping(value = "runit/family", method = RequestMethod.POST)
       public void handle(@RequestBody List<Person> myFamily) throws Exception {
              System.out.println(myFamily); //until here, it is fine

              JobParameters jobParameters = new JobParametersBuilder()
                           .addParameter("parametersReceived", (JobParameter) myFamily)
                           .addLong("time", System.currentTimeMillis()).toJobParameters();

              jobLauncher.run(job, jobParameters);
       }

SoapUi (post):

[{"firstName":"aa","lastName":"bb"}]

波乔

public class Person {

    private String lastName;
    private String firstName;
    ...getters and setters

可能的工作方式,但我对这个 Jira 问题真的很困惑。老实说,我期待一些更简单的方法,就像我尝试使用 JobParameter

https://jira.spring.io/browse/BATCH-966 (this suggestion is from 2009. Probably some more up-to-date technique is available)
<bean class="MyItemReader">
<property name="dynamicValuesHashMap" ref="map"/>
...
</bean>

<bean class="MyLauncher">
<property name="dynamicValuesHashMap" ref="map"/>
...
</bean>

整个错误:

java.lang.ClassCastException: java.util.ArrayList cannot be cast to org.springframework.batch.core.JobParameter

       at hello.BatchController.handle(BatchController.java:42)

       at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)

       at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)

       at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)

       at java.lang.reflect.Method.invoke(Method.java:497)

       at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:221)

       at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:137)

       at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:110)

       at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandleMethod(RequestMappingHandlerAdapter.java:776)

       at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:705)

       at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:85)

       at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:959)

       at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:893)

       at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:967)

       at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:869)

       at javax.servlet.http.HttpServlet.service(HttpServlet.java:648)

       at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:843)

       at javax.servlet.http.HttpServlet.service(HttpServlet.java:729)

       at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:291)

       at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)

       at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)

       at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:239)

       at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)

       at org.springframework.web.filter.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:77)

       at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)

       at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:239)

       at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)

       at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:85)

       at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)

       at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:239)

       at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)

       at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:219)

       at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:106)

       at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:502)

       at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:142)

       at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:79)

       at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:88)

       at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:518)

       at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1091)

       at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:668)

       at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1521)

       at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.run(NioEndpoint.java:1478)

       at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)

       at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)

       at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)

       at java.lang.Thread.run(Thread.java:745)

批处理作业是基于时间的,而不是基于事件的。因此,您无法将信息从 Rest 服务传递到您的 Job 实例。在您在控制器方法中触发作业之前,将列表写入临时平面文件或将其存储在数据库中,您的作业可以从中读取它。

如果您查看 spring batch 的实际 schema which stores meta data,您将看到作业支持的可用类型列表作为参数(有 string_valdate_vallong_val, double_val).因此,当作业启动时,每个作业参数都保存在数据库中,其中 key_name 作为参数名称,值存储在提到的 _val table 之一中。 type_cd 提示使用了哪种类型。

JobParameter 的文档也给出了可以用作作业参数的提示:

Domain representation of a parameter to a batch job. Only the following types can be parameters: String, Long, Date, and Double. The identifying flag is used to indicate if the parameter is to be used as part of the identification of a job instance.

我认为最好的方法是在存储参数列表的数据库中创建 table 并将该记录的 ID 作为 JobParameter 传递,或者将列表序列化为 json 并传递它作为 String 在工作中作为 JobParameter。如果您选择第二个选项,请注意 string_val 在数据库中存储为 varchar 250,因此限制为 250 个字符。