surefire for spring-boot/surefire incompatibility
diff --git a/pom.xml b/pom.xml
index f892463..bc78af5 100644
--- a/pom.xml
+++ b/pom.xml
@@ -35,7 +35,7 @@
<developerConnection>scm:git:https://gitbox.apache.org/repos/asf/geronimo-batchee.git</developerConnection>
<url>https://gitbox.apache.org/repos/asf/geronimo-batchee.git</url>
<tag>HEAD</tag>
- </scm>
+ </scm>
<properties>
diff --git a/tools/spring-boot-batchee-ui/pom.xml b/tools/spring-boot-batchee-ui/pom.xml
index d85af64..e74fca9 100644
--- a/tools/spring-boot-batchee-ui/pom.xml
+++ b/tools/spring-boot-batchee-ui/pom.xml
@@ -39,15 +39,15 @@
<version>${project.version}</version>
</dependency>
<dependency> <!-- for jsp -->
- <groupId>org.apache.tomcat</groupId>
- <artifactId>tomcat-jasper</artifactId>
+ <groupId>org.apache.tomcat.embed</groupId>
+ <artifactId>tomcat-embed-jasper</artifactId>
<version>9.0.54</version>
</dependency>
<dependency>
- <groupId>org.springframework.batch</groupId>
- <artifactId>spring-batch-core</artifactId>
- <version>4.3.3</version>
+ <groupId>org.springframework.boot</groupId>
+ <artifactId>spring-boot-starter-batch</artifactId>
+ <version>${spring-boot.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
diff --git a/tools/spring-boot-batchee-ui/src/test/java/org/apache/batchee/spring/ui/BatchEEUITest.java b/tools/spring-boot-batchee-ui/src/test/java/org/apache/batchee/spring/ui/BatchEEUITest.java
index e3c2501..18bb1f8 100644
--- a/tools/spring-boot-batchee-ui/src/test/java/org/apache/batchee/spring/ui/BatchEEUITest.java
+++ b/tools/spring-boot-batchee-ui/src/test/java/org/apache/batchee/spring/ui/BatchEEUITest.java
@@ -17,6 +17,7 @@
package org.apache.batchee.spring.ui;
import com.zaxxer.hikari.HikariDataSource;
+import org.apache.catalina.WebResourceRoot;
import org.junit.Test;
import org.springframework.batch.core.BatchStatus;
import org.springframework.batch.core.Job;
@@ -35,85 +36,113 @@
import org.springframework.batch.repeat.RepeatStatus;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
-import org.springframework.boot.context.event.ApplicationReadyEvent;
+import org.springframework.boot.web.embedded.tomcat.TomcatContextCustomizer;
import org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.http.ResponseEntity;
+import org.springframework.web.client.HttpClientErrorException;
import org.springframework.web.client.RestTemplate;
import javax.sql.DataSource;
+import java.net.MalformedURLException;
+import java.net.URL;
import java.util.concurrent.CountDownLatch;
-import java.util.concurrent.atomic.AtomicReference;
+import static java.lang.Thread.sleep;
+import static org.apache.catalina.Lifecycle.CONFIGURE_START_EVENT;
+import static org.apache.catalina.WebResourceRoot.ResourceSetType.RESOURCE_JAR;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
public class BatchEEUITest {
@Test
- public void ensureUIRuns() {
+ public void ensureUIRuns() throws InterruptedException {
try (final ConfigurableApplicationContext ctx = runBatch()) {
- assertUIIsThere(ctx);
+ final int maxRetries = 10;
+ for (int i = 1; i <= maxRetries; i++) {
+ try {
+ assertUIIsThere(ctx);
+ break;
+ } catch (final HttpClientErrorException.NotFound ae) {
+ if (i == maxRetries) {
+ throw ae;
+ }
+ sleep(250);
+ }
+ }
}
}
private ConfigurableApplicationContext runBatch() {
final SpringApplication app = new SpringApplication(BatchApp.class);
- final AtomicReference<JobExecution> done = new AtomicReference<>(null);
- final AtomicReference<ConfigurableApplicationContext> context = new AtomicReference<>(null);
- app.addListeners(applicationEvent -> {
- if (!ApplicationReadyEvent.class.isInstance(applicationEvent)) {
- return;
- }
+ final JobExecution done;
+ final ConfigurableApplicationContext ctx = app.run("--server.port=0", "--server.tomcat.basedir=target/tomcat");
+ try {
+ done = ctx.getBean(JobLauncher.class).run(ctx.getBean(Job.class), new JobParameters());
+ ctx.getBean(Awaiter.class).latch.await();
+ } catch (final JobExecutionAlreadyRunningException | JobRestartException |
+ JobInstanceAlreadyCompleteException | JobParametersInvalidException |
+ InterruptedException e) {
+ throw new IllegalStateException(e);
+ }
- final ConfigurableApplicationContext ctx = ApplicationReadyEvent.class.cast(applicationEvent)
- .getApplicationContext();
- context.set(ctx);
- try {
- done.set(ctx.getBean(JobLauncher.class).run(ctx.getBean(Job.class), new JobParameters()));
- ctx.getBean(Awaiter.class).latch.await();
- } catch (final JobExecutionAlreadyRunningException | JobRestartException |
- JobInstanceAlreadyCompleteException | JobParametersInvalidException |
- InterruptedException e) {
- throw new IllegalStateException(e);
- }
- });
- app.run("--server.port=0", "--server.tomcat.basedir=target/tomcat");
-
- final JobExecution exec = done.get();
- assertNotNull(exec);
-
- final JobExecution jobExecution = context.get().getBean(JobExplorer.class).getJobExecution(exec.getJobId());
+ final JobExecution jobExecution = ctx.getBean(JobExplorer.class).getJobExecution(done.getJobId());
assertNotNull(jobExecution);
assertEquals(BatchStatus.COMPLETED, jobExecution.getStatus());
- return context.get();
+ return ctx;
}
- // snaity checks to ensure the UI is properly rendered
+ // sanity checks to ensure the UI is properly rendered
private void assertUIIsThere(final ConfigurableApplicationContext ctx) {
final int port = ServletWebServerApplicationContext.class.cast(ctx).getWebServer().getPort();
- { // home
- final ResponseEntity<String> home = new RestTemplate().getForEntity("http://localhost:" + port + "/batchee/", String.class);
- assertEquals(200, home.getStatusCodeValue());
- final String body = home.getBody();
- assertNotNull(body);
- assertTrue(body, body.contains("<h3 class=\"text-muted\">Apache JBatch GUI</h3>"));
- assertTrue(body, body.contains("<a href=\"/batchee/executions/BatchEEUITestBatch\">BatchEEUITestBatch</a>"));
- }
- { // detail for the batch
- final ResponseEntity<String> home = new RestTemplate().getForEntity("http://localhost:" + port + "/batchee/executions/BatchEEUITestBatch", String.class);
- assertEquals(200, home.getStatusCodeValue());
- final String body = home.getBody();
- assertNotNull(body);
- assertTrue(body, body.contains("<td>COMPLETED</td>"));
- assertTrue(body, body.contains("<td><a href=\"/batchee/step-executions/1\">1</a></td>"));
- }
+ assertHome(port);
+ assertDetails(port);
+ }
+
+ private void assertDetails(final int port) {
+ final ResponseEntity<String> home = new RestTemplate().getForEntity("http://localhost:" + port + "/batchee/executions/BatchEEUITestBatch", String.class);
+ assertEquals(200, home.getStatusCodeValue());
+ final String body = home.getBody();
+ assertNotNull(body);
+ assertTrue(body, body.contains("<td>COMPLETED</td>"));
+ assertTrue(body, body.contains("<td><a href=\"/batchee/step-executions/1\">1</a></td>"));
+ }
+
+ private void assertHome(final int port) {
+ final ResponseEntity<String> home = new RestTemplate().getForEntity("http://localhost:" + port + "/batchee/", String.class);
+ assertEquals(200, home.getStatusCodeValue());
+ final String body = home.getBody();
+ assertNotNull(body);
+ assertTrue(body, body.contains("<h3 class=\"text-muted\">Apache JBatch GUI</h3>"));
+ assertTrue(body, body.contains("<a href=\"/batchee/executions/BatchEEUITestBatch\">BatchEEUITestBatch</a>"));
}
@EnableBatchProcessing
@SpringBootApplication
public static class BatchApp {
+ @Bean // StaticResourceJars fails with surefire classloader so let's workaround it for the test
+ public TomcatContextCustomizer surefireStaticResourceJarsWorkaround() {
+ return context -> context.addLifecycleListener(event -> {
+ if (!event.getType().equals(CONFIGURE_START_EVENT)) {
+ return;
+ }
+
+ final URL url = Thread.currentThread().getContextClassLoader()
+ .getResource("META-INF/resources/internal/batchee/layout.jsp");
+ final WebResourceRoot resources = context.getResources();
+ try {
+ final URL cleanUrl = new URL(
+ url.getProtocol(), url.getHost(), url.getPort(),
+ url.getFile().substring(0, url.getFile().length() - "META-INF/resources/internal/batchee/layout.jsp".length()));
+ resources.createWebResourceSet(RESOURCE_JAR, "/", cleanUrl, "/META-INF/resources");
+ } catch (final MalformedURLException e) {
+ throw new IllegalStateException(e);
+ }
+ });
+ }
+
@Bean(destroyMethod = "close")
public DataSource dataSource() {
final HikariDataSource dataSource = new HikariDataSource();