StepScope vs JobScope - spring

I went through all the pages in the internet about the StepScope and JobScope and still not sure what is the clear difference and where to use which one
My Understanding
StepScope : Different instance for each step execution.
JobScope : Only one instance per executing job.
Can someone please explain it clearly?
Thanks

Related

Spring Batch: Implementing stop method in StoppableTasklets

I am calling the following piece to stop the job.
Set<Long> executions = jobOperator.getRunningExecutions("Job-Builder");
jobOperator.stop(longExecutions.iterator().next());
The above method is stopping the job but Tasklets are still running. After reading through comments from stackoverflow I changed tasklet to use StoppableTasklet in my project so that I can stop them from running when I call the joboperator.stop()
My question here is that I am not sure how to identify if a job has been stopped and do necessary action inside the stop overriden method when I implement StoppableTasklet. Can you tell me on how I can do that in the overridden method?
My question here is that I am not sure how to identify if a job has been stopped and do necessary action inside the stop overriden method when I implement StoppableTasklet
You don't need to identify if the job has been stopped in your code. You need to implement the logic to stop the current tasklet and this logic will be called by the framework when you stop the job through JobOperator#stop.

Spring Batch Step Integration Testing

I'm looking for some general opinions and advice on testing a Spring batch step and step execution.
My basic step reads in from an api, processes into an entity object and then writes to a DB. I have tested the happy path, that the step completes successfully. What I now want to do is test the exception handling when data is missing at the processor stage. I could test the processor class in isolation, but I'd rather test the step as a whole to ensure the process failure is reflected correctly at step/job level.
I've read the spring batch testing guidelines and if I'm honest, I'm slightly lost within it. Is it possible to use StepScopeTestUtils.doInStepScope or updating the StepExecution to test this scenario? Ideally I'd force the reader to return faulty data before the processor kicks in.
Any advice would be greatly appreciated.
The best approach depends on the scope of your test. Reading a little between the lines here, I assume you are using a Spring IT, setting up a Spring context and using the JobLauncherTestUtils to start a job or a step.
I think the easiest way is replace one of your beans with a mock that triggers the error scenario. Using Mockito, this can be done by adding something like this to your test-configuration.
#Bean
public ReaderDataRepository dataApi(){
return mock(ReaderDataRepository.class);
}
This bean then overrides the actual implementation. In the test setup you can then configure this mock very explicitly.
#Autowired
private ReaderDataRepository mockedRepository;
#Before
public void setUp() {
when(mockedRepository.getData()).thenReturn(faultyData())
}
This involves very little manipulation of Spring 'magic' and very explicitly defines the error from within the test.

Spring.datasource.initialize=false not working

I am working on spring boot and batch application.
Due to batch, the application tries to connect to datasource
with spring-boot:run.
I want to stop that and tried spring.datasource.initialize=false
Along with this also put spring.batch.job.enabled=false
While the second one works fine, it seems the first one is ignored.
Could someone let me know if there is a way to stop db connection on startup?
Thanks in advance
The problem is, that spring/spring-boot loads the whole spring-context when it is "booted". This means, that all defined spring-beans are loaded into the spring-context during this boot-phase. In the case of spring-batch, this also means that the datasource bean is loaded and, if not turned off by "spring.batch.initializer.enabled=false", the spring-batch tables are initialized.
Generally, you cannot prevent this from happening as soon as you have added your spring-batch-starter to your maven dependencies.
Moreover, I don't understand why you want to prevent this from happening. It is just initialisation taking place and, provided that everything is configured correctly, this shouldn't be a problem at all.
Nonetheless, if you really want to stop the datasource from beeing initialized, you could try the following approach. However, I don't know if this will work.
Spring-Batch needs a datasource that is registered under the name "dataSource" in the spring-context. If no spring-bean with that name is found, it creates its own. But if you provide your own implementation/configuration for it, it will use your spring bean.
What you need to do is, to provide a proxy for a datasource that is loaded lazily and then register it under the name "dataSource" in the context:
#Configuration
public class MySetUp {
#Bean
public DataSource dataSource() {
// ... create your "lazy initializing" datasource
}
}
But - and let me stress that - this nothing that I would recommend and I don't see a good reason, why this should be necessary to do.
Furthermore, you mention that you only want load "initial static index page" (I assume, you are talking about html, right?). However, I don't see a "batch" use case, which should display html-pages. It would probably be better to have two different applications in this case.
Probably you could provide some more information about your use case.
As I understand, you don't want to prevent database connection during application startup.
Instead, you want to prevent execution of batch scripts.
Correct me, please, if I got it wrong.
To prevent execution of batch scripts set:
spring.batch.initializer.enabled=false

Exception BeanFactory must be set on AnnotationAsyncExecutionAspect to access qualified executor

I created a public method with #Async and I also have a bean for that class in which this method is created. But when I am calling it , it is not behaving async and getting blocked. Then I created a executor in application-bean and used #Async(value = “executorname”), even this is not working and on every call I am getting “beanFactory must be set on AnnotationasyncExecutionAspect to access qualified executor”.
in my application bean.xml I have
there are then few executors and schedulers and I want to use one new executor.
Please tell me how to get away with this error and get async behaviour
Thanks in advance
I was experiencing exactly the same issue and find out a solution I hope works for you (https://jira.spring.io/browse/SPR-10276).
Apparently if you unabled Spring's AspectJ aspects into your project (by using aspectj-maven-plugin, for instance), Spring's Async mechanism can be placed twice in your bean, one by aspectj and other by proxy. But, since it doesn't know it, AnnotationAsyncExecutionAspect will not be injected with a BeanFactory and you will see the assertion exception you had.
To fix it, you must instruct Spring's Async mechanism to use the AspectJ support. Do this incluing this in your Application Context.
<task:annotation-driven mode="aspectj"/>
I hope I could be of any help.
For annotation based configuration you can use #EnableAsync(mode = AdviceMode.ASPECTJ)

Grails services and Spring task scheduling

I have a Grails 2.0.1 webappp which should run some task each couple of hours. I'm using Spring's integrated task scheduling to make this happen so I don't need yet another plugin.
However, when I'm trying to do anything with the database, like save a model, I get the following error message:
Message: No signature of method: rssreader.Feed.save() is applicable for argument types: () values: []
Possible solutions: save(), save(boolean), save(java.util.Map), wait(), any(), wait(long)
With the following code:
#Transactional
class FeedRefresherService {
#Scheduled(fixedDelay = 3000L)
public void madeUpMethod() {
def feed = new Feed()
feed.title = "Test feed"
feed.save()
}
}
I believe this has something to do with the GORM methods not being available because of the scheduling, but I'm not sure how to proceed from here.
Does anybody have a clue?
I think your Hibernate Session got "disconnected" I have faced similar error in past, but do not remember how I resolved it...:(
For task scheduling you could use quartz plugin which is quite stable, I have been using it in production for quite some time. Take a look at the source code of the Executor plugin which deals with associating hibernate sessions with multiple threads, while it may not solve your problem, it might give you a lead on how to tackle it.

Resources