Skip to content
Permalink
Browse files
surefire for spring-boot/surefire incompatibility
  • Loading branch information
rmannibucau committed Oct 27, 2021
1 parent a654329 commit eb02bae9f70944f44316ae4bea0f2615e34846b9
Showing 3 changed files with 81 additions and 52 deletions.
@@ -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>
@@ -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>
@@ -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 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 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 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();

0 comments on commit eb02bae

Please sign in to comment.