14

I have a requirement of sending a Custom Object to the Spring Batch Job , where this Object is used continuously used by the Item Processor for the business requirement.

How can we send custom object from outside to the Job Context. This Object changes from Job to Job and generated at runtime depending on Business case.

How can send this as a Job Parameter? or is there any way that i can set this Object to the respective Job ?

can overriding Spring JobParameter help me in any way? or are there any Big issues as an outcome of this Overriding behaviour ?

ravinder reddy
  • 309
  • 1
  • 4
  • 17
  • 1
    Is there anything stopping this object from being a bean (or in a container bean) that you can just wire into your processor? – DBK Nov 18 '15 at 03:56
  • @DBK .yes, it is an entity read from database. and for each job, i have to use different entities depending on the functional need. – ravinder reddy Nov 18 '15 at 20:16
  • 1
    The easiest way for me was to serialize Object to Json and put it to String job parameter – Eugene To May 15 '17 at 08:03

5 Answers5

8

Use the below class to send CustomObject.

public static class CustomJobParameter<T extends Serializable> extends JobParameter {
        private T customParam;
        public CustomJobParameter(T customParam){
            super(UUID.randomUUID().toString());//This is to avoid duplicate JobInstance error
            this.customParam = customParam;
        }
        public T getValue(){
            return customParam;
        }
    }

===========================

Usage:

  1. Sending parameter:

    JobParameters paramJobParameters = new JobParametersBuilder().addParameter("customparam", new CustomJobParameter<MyClass>(myClassReference)).toJobParameters();

  2. Retrieving parameter:

    MyClass myclass = (MyClass)jobExecution.getJobParameters().getParameters().get("customparam").getValue();

manoj
  • 139
  • 2
  • 2
  • i implemented this but it causes my Job execution to fail. @manoj – Sanjay Naik Jul 02 '21 at 12:58
  • Maybe, you must define the CustomJobParameter as final class and not static class – Joe Taras Sep 09 '21 at 08:37
  • This is bad, you're only storing UUID in the database, if you restart your job after failure, retrieving parameter like you showed will give a class cast exception, as `getValue()` will return the UUID instead of MyClass – Sam Nov 16 '21 at 16:13
6

This question has been asked on the offical Spring Batch forum : http://forum.spring.io/forum/spring-projects/batch/96660-how-to-pass-complex-objects-to-job-launcher

A Jira was open then but the developpers chose not to resolve it (Won't fix) : https://jira.spring.io/browse/BATCH-966

An alternative solution for a more or less identical case (passing a stream as a JobParameter) was discussed here : Passing stream to job as parameter


To summarize, the answer is no you can only pass primitive types as JobParameters and overriding it seems to be discouraged. The alternative solutions are to either declare and inject a Bean with your parameters or to use a static variable to access it project-wide.

Community
  • 1
  • 1
Thrax
  • 1,926
  • 1
  • 17
  • 32
6

I have summarized reasons why you cannot send object as JobParameter in this question. There are couple of ideas on that question how you can do it.

TL:TR: I think best way would be either to create table in DB which stores Object and pass id of that record as JobParameter or to serialize Object to json and pass it as String in job as JobParameter. If you go with second option be aware that string_val is stored in DB as varchar 250 so limit is 250 characters.

Community
  • 1
  • 1
Nenad Bozic
  • 3,724
  • 19
  • 45
  • thanks for the reply bozic. i have already implemented serilization using Json..i was looking for any other options available of my curiousity ..any way thanks so for the for the response – ravinder reddy Nov 20 '15 at 21:12
0

You would use ThreadLocal before init the job execution, there is a tutorial in spanish about how to use ThreadLocal:

http://aquiseprograma.co/2015/09/como-pasar-variables-o-valores-entre-metodos-sin-que-sea-como-parametro-dentro-del-mismo-hilo-de-ejecucion-en-java-threadlocal/

maframaran
  • 170
  • 9
0

I've found a way just if your string parameter length is fixed, but it is greater than 250. Just split it into pieces of 250, then, within the XML configuration use Spring EL in this way:

Set your parameter in your main Class like this:

JobParametersBuilder parametersBuilder = new JobParametersBuilder();
parametersBuilder.addString("useful.parameter.1", headers.substring(0, 250));
parametersBuilder.addString("useful.parameter.2", headers.substring(250, 500));
parametersBuilder.addString("useful.parameter.3", headers.substring(500, headers.length()));

Configure your parameters and the scope in "step":

<bean id="someStep01Writer" class="path.to.some.StepWriter" scope="step">
    <property name="someUsefulProperty" value="#{jobParameters['useful.parameter.1'] + jobParameters['useful.parameter.2'] + jobParameters['useful.parameter.3']}"/>
</bean>

Hope it helps.

Gabriel Villacis
  • 331
  • 7
  • 17