Skip to content

Update Task to BOOT 2.1.M1 #441

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 9 commits into from
Closed

Conversation

cppwfs
Copy link
Collaborator

@cppwfs cppwfs commented Aug 15, 2018

Migrating to use ApplicationContextRunner or ImportAutoConfiguration with SpringApp.run, instead of SpringApplicationBuilder, because builder does not handle AutoConfiguration properly

SimpleTaskAutoConfiguration now has an annotation AutoConfigureBefore the BatchTaskAutoConfig so that it is processed prior. THis is so that that BatchTaskAutoConfig can create the appropriate beans

SimpleTaskAutoConfiguration has new annotations so that it is AutoConfigured after BindingServiceConfiguration and after SimpleTaskAutoConfiguration. This is so that it does not attempt to start emitting messages before stream is ready and it can create the appropriate beans after SimpleTaskAutoConfiguration has run.

Renamed SimpleTaskConfiguration to SimpleTaskAutoConfiguration.

Task version updated to 2.1.0

Added missing headers

Updated documentation.

Deprecated EnableTask

Added ability to disable Task autoconfiguration.

Removed @EnableTask from tests

Replaced TaskListenerExecutorFactory with TaskListenerExecutorObjectProviderTests. This delays the need to acquire a bean till it is needed vs at application event time.

Resolves #439
Resolves #440
Resolves #448
Resolves #455
Resolves #461
Resolves #466
Resolves #465

Copy link
Contributor

@mminella mminella left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I also don't see a test confirming that using the annotation (even though it's depricated) does't break anything.

String[] enabledArgs = new String[] { "--spring.cloud.task.batch.failOnJobFailure=true" };
String[] enabledArgs = new String[] {
"--spring.cloud.task.batch.failOnJobFailure=true",
"--spring.batch.job.enabled=false"};// batch job enabled is turned to false so that we can use Task's JobLauncher
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why did the need for this change between Boot 1 and Boot 2?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

More importantly, what happened between 2.0 and 2.1 ;-) In short we have 2 beans vying for the JobLauncher, the one provided by boot and the one we provide if the user wants a Task to fail the execution when a batch job fails. Since we don't have bean overriding by default, we have to disable the default boot provided JobLauncher

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That doesn't answer what changed...we had that feature before, right? This test implies that going forward, users of this functionality will need to set this property (which is a different behavior from the way we did this before).

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We were using bean overriding before. If a user set the failOnJobFailure to true we would override the JobLauncher provided by boot. As of 2.1 we it will not allow that unless we set the flag to re-enable bean overriding or we disable boots default joblauncher.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So we're saying that this breaks the existing functionality?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yep. Unless they add one of the two flags.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmmm....We should talk about this.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

agreed

@cppwfs
Copy link
Collaborator Author

cppwfs commented Oct 16, 2018

Added tests that utilize the deprecated @EnableTask.

@cppwfs
Copy link
Collaborator Author

cppwfs commented Oct 25, 2018

Rebased

Copy link
Contributor

@mminella mminella left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not all of these comments are a direct result of the desired update. Specifically the comments around the BatchStatus vs ExitStatus. That's a miss from the original functionality but we should fix it. The question is if it's part of this PR or another one.

@@ -43,6 +43,21 @@
*/
private int commandLineRunnerOrder = 0;

/**
* Maximum wait time that Spring Cloud task will wait for tasks to complete
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

capitalize T on Task.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

* when spring.cloud.task.batch.failOnJobFailure is set to true. Defaults
* to 5000.
*/
private long failOnJobFailurePollIntervalInMillis = 5000l;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not a fan of naming a variable with the units. I'd rather document it via javadoc. Do we have other examples within the Spring ecosystem where we take this approach to variable naming?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes. https://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/util/StopWatch.html
But in the end, our project may have a different standard.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated

* when spring.cloud.task.batch.failOnJobFailure is set to true. Defaults
* to 5000.
*/
private long failOnJobFailurePollIntervalInMillis = 5000l;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same points from the properties apply here since these seem to have been copied and pasted. Beyond that, why are we duplicating those fields here and not just referencing the properties values directly? We repeat the values for this in the properties object, the factory bean, and the object itself. Seems pretty redundant to me.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Replace with TaskBatchProperties.


public void setFailOnJobFailurePollIntervalInMillis(long failOnJobFailurePollIntervalInMillis) {
this.failOnJobFailurePollIntervalInMillis = failOnJobFailurePollIntervalInMillis;
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why getters for properties on a factory bean?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

removed

* Can also be used to launch a specific job by providing a jobName. The
* jobs in the surrounding context by default and throw an exception upon the first job
* that returns an {@link ExitStatus} of FAILED if a {@link TaskExecutor} is not
* specified. If a {@link TaskExecutor} is specified then all Jobs are launched and an
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If a TaskExecutor' is specified where (there isn't one in this class)? You really mean if the provided JobLauncherexecutes the jobs in an asynchronous manor, then you get the behavior of all jobs being launched and us throwing the exception if any of them fail vs if theJobLauncher` executes the job in an synchronous manor, then you get the behavior of we check each job as it's executed.

Copy link
Collaborator Author

@cppwfs cppwfs Oct 25, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The TaskExecutor is applied to the JobLauncher and this class really never touches it.

To the second question: Yes.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

import org.springframework.boot.autoconfigure.ImportAutoConfiguration;

/**
* Contains the common configurations to run a unit test for the task batch features of
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What configurations, specifically, are brought in?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Look in src/test/resources/META-INF/spring.factories

@@ -54,11 +53,15 @@
* </ul>
*
* @author Glenn Renfro
*
* @deprecated The EnableTask annotation is no longer be required to initialize
* Spring Cloud Task. This will be handled by Spring Boot AutoConfiguration.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is handled by the auto configuration provided in Spring Cloud Task via our starter...Spring Boot by itself doesn't handle this.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

updated

@@ -126,7 +126,7 @@
<profile>
<id>skipIntegrationTests</id>
<activation>
<activeByDefault>true</activeByDefault>
<activeByDefault>false</activeByDefault>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why was this switched?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

reset

Migrating to use ApplicationContextRunner or ImportAutoConfiguration with SpringApp.run, instead of SpringApplicationBuilder, because builder does not handle AutoConfiguration properly

SimpleTaskAutoConfiguration now has an annotation AutoConfigureBefore the BatchTaskAutoConfig so that it is processed prior.  THis is so that that BatchTaskAutoConfig can create the appropriate beans

SimpleTaskAutoConfiguration has new annotations so that it is AutoConfigured after BindingServiceConfiguration and after SimpleTaskAutoConfiguration.  This is so that it does not attempt to start emitting messages before stream is ready and it can create the appropriate beans after SimpleTaskAutoConfiguration has run.

Renamed SimpleTaskConfiguration to SimpleTaskAutoConfiguration.

Task version updated to  2.1.0

Added missing headers

Updated documentation.

Deprecated EnableTask

Added ability to disable Task autoconfiguration.

Removed @EnableTask from tests

Resolves spring-cloud#439
Resolves spring-cloud#440
…tialisation

Replaced TaskListenerExecutorFactory with TaskListenerExecutorObjectProviderTests.  This delays the need to acquire a bean till it is needed vs at application event time.

resolves spring-cloud#448
Updated to add regression tests for @EnableTask to verify no negative impact when in use.
…LineRunner

Used to be a copy of.  No just inherits.

Added feature check for completed/failed jobs before throwing exception

Currently in Task if the user sets failOnJobFailure and they are using a TaskExecutor it will not throw an exception when task fails.
This because at evaluation time the job has not started.
With the latest change Task waits for all jobs to complete before deciding whether an exception needs to be thrown or not.
* term millis removed from class attributes and moved to docs
* timeout attributes removed from TaskJobLauncherCommandLinerRunnerFactory Bean and TaskJobLauncherCommandLineRunner
* TaskBatchTest moved to configuration package
* Documentation updated
* pom.xml reset
* rebased conflicts resolved
* TaskJobLauncherCommandLineRunner uses BatchStatus instead of exitCode
to determine if a Job has failed.

resolves spring-cloud#466
Copy link
Contributor

@mminella mminella left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

JobRepository won't work like this. The rest I can handle on merge.

JobRepositoryFactoryBean factoryBean = new JobRepositoryFactoryBean();
factoryBean.setDataSource(dataSource);
return factoryBean.getObject();
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The fact that we need to do this means we're doing something wrong. There should only be one JobRepository for the context. Especially were are assuming default settings which may not be the case. There are more ways to customize a JobRepository implementation than just passing a DataSource that would impact if it even works.

Job job = this.jobRegistry.getJob(jobName);
if (this.jobs.contains(job)) {
continue;
private void validateJobExecutions() {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This isn't really validating anything. May rename this method to something more prescriptive.

String message = "The following Jobs have failed: \n";
for (JobExecution failedJobExecution : failedJobExecutions) {
message += String.format("Job %s failed during " +
"execution for jobId %s with jobExecutionId of %s \n",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

jobId is really JobInstance ID

Map<String, JobParameter> merged = new HashMap<>();
merged.putAll(parameters.getParameters());
merged.putAll(additionals.getParameters());
return new JobParameters(merged);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

White space is your friend (between methods at a minimum).

@@ -79,12 +90,14 @@

@Before
public void init() {
batchConfigurer.clear();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We're using @DirtiesContext on some tests...beyond this, what else would we need to clear out? Why not just use @DirtiesContext?

};
Throwable exception = assertThrows(JobRestartException.class, executable);
AssertionsForClassTypes.assertThat(exception.getMessage())
.isEqualTo("JobInstance already exists and is not restartable");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do we run the job twice above, then do a third time? Shouldn't we be able to assert what we need to on the second run?

TaskBatchAutoConfiguration.class,
TaskJobLauncherAutoConfiguration.class,
SingleTaskConfiguration.class,
SimpleTaskAutoConfiguration.class })
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Doesn't the @TaskBatchTest annotation bring in a subset of these?

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@Import({ SimpleTaskConfiguration.class, SingleTaskConfiguration.class })
@Import({ })
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do we have an empty @Import?

@@ -374,4 +390,5 @@ public int getPhase() {
public void destroy() throws Exception {
this.doTaskEnd();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why aren't we removing this line?

@mminella
Copy link
Contributor

mminella commented Nov 1, 2018

Rebased, polished, and merged. Thanks for all the work on this one!

@mminella mminella closed this Nov 1, 2018
@mminella mminella removed the in pr label Nov 1, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants