Skip to content

Commit

Permalink
test(engine-rest): retry server start when port still bound (camunda#…
Browse files Browse the repository at this point in the history
…3536)

* Supports retrying server startups when the address is still bound.
  Occasionally, the OS can take more time to release the port physically
  after we stop our test server instance. Before we start it again for the
  next test class, we might have to wait and retry.

related to camunda#3535
  • Loading branch information
tmetzke authored Jul 4, 2023
1 parent 81c1b1d commit 6249ebb
Show file tree
Hide file tree
Showing 8 changed files with 190 additions and 106 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,12 @@
*/
package org.camunda.bpm.engine.rest.util.container;

import java.util.HashMap;
import java.util.Map;

import io.undertow.servlet.Servlets;
import io.undertow.servlet.api.DeploymentInfo;
import jakarta.servlet.DispatcherType;
import jakarta.ws.rs.core.Application;

import java.util.HashMap;
import java.util.Map;
import org.camunda.bpm.engine.rest.CustomJacksonDateFormatTest;
import org.camunda.bpm.engine.rest.ExceptionHandlerTest;
import org.camunda.bpm.engine.rest.application.TestCustomResourceApplication;
Expand Down Expand Up @@ -126,6 +124,7 @@ public class ResteasySpecifics implements ContainerSpecifics {
.addFilterUrlMapping("Resteasy", "/*", DispatcherType.REQUEST)));
}

@Override
public TestRule getTestRule(Class<?> testClass) {
TestRuleFactory ruleFactory = DEFAULT_RULE_FACTORY;

Expand All @@ -144,15 +143,18 @@ public EmbeddedServerRuleFactory(Application jaxRsApplication) {
this.jaxRsApplication = jaxRsApplication;
}

@Override
public TestRule createTestRule() {
return new ExternalResource() {

ResteasyServerBootstrap bootstrap = new ResteasyServerBootstrap(jaxRsApplication);

@Override
protected void before() throws Throwable {
bootstrap.start();
}

@Override
protected void after() {
bootstrap.stop();
}
Expand All @@ -168,17 +170,20 @@ public UndertowServletContainerRuleFactory(DeploymentInfo deploymentInfo) {
this.deploymentInfo = deploymentInfo;
}

@Override
public TestRule createTestRule() {
final TemporaryFolder tempFolder = new TemporaryFolder();

return RuleChain.outerRule(tempFolder).around(new ExternalResource() {

final EmbeddedServerBootstrap bootstrap = new ResteasyUndertowServerBootstrap(deploymentInfo);
final AbstractServerBootstrap bootstrap = new ResteasyUndertowServerBootstrap(deploymentInfo);

@Override
protected void before() {
bootstrap.start();
}

@Override
protected void after() {
bootstrap.stop();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,30 +17,50 @@
package org.camunda.bpm.engine.rest.util.container;

import io.undertow.servlet.api.DeploymentInfo;
import org.jboss.resteasy.plugins.server.undertow.UndertowJaxrsServer;

import java.net.BindException;
import java.util.Properties;
import org.jboss.resteasy.plugins.server.undertow.UndertowJaxrsServer;

public class ResteasyUndertowServerBootstrap extends EmbeddedServerBootstrap {
public class ResteasyUndertowServerBootstrap extends AbstractServerBootstrap {

private UndertowJaxrsServer server;
protected UndertowJaxrsServer server;
protected DeploymentInfo deploymentInfo;

public ResteasyUndertowServerBootstrap(DeploymentInfo deploymentInfo) {
Properties serverProperties = readProperties();
int port = Integer.parseInt(serverProperties.getProperty(PORT_PROPERTY));

this.server = new UndertowJaxrsServer();
this.server.setPort(port);
this.server.deploy(deploymentInfo);
this.deploymentInfo = deploymentInfo;
setupServer();
}

@Override
public void start() {
this.server.start();
public void stop() {
this.server.stop();
}

@Override
public void stop() {
this.server.stop();
protected void startServer(int startUpRetries) {
try {
this.server.start();
} catch (Exception e) {
if ((e instanceof BindException || e.getCause() instanceof BindException) && startUpRetries > 0) {
stop();
try {
Thread.sleep(1500L);
} catch (Exception ex) {
}
setupServer();
startServer(--startUpRetries);
} else {
throw new ServerBootstrapException(e);
}
}
}

protected void setupServer() {
Properties serverProperties = readProperties();
int port = Integer.parseInt(serverProperties.getProperty(PORT_PROPERTY));

this.server = new UndertowJaxrsServer();
this.server.setPort(port);
this.server.deploy(this.deploymentInfo);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,41 +16,41 @@
*/
package org.camunda.bpm.engine.rest.util.container;

import org.glassfish.grizzly.http.server.HttpServer;
import org.glassfish.jersey.grizzly2.httpserver.GrizzlyHttpServerFactory;
import org.glassfish.jersey.server.ResourceConfig;
import org.glassfish.jersey.server.ServerProperties;

import javax.ws.rs.core.Application;
import javax.ws.rs.core.UriBuilder;
import java.io.IOException;
import java.net.URI;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
import javax.ws.rs.core.Application;
import javax.ws.rs.core.UriBuilder;
import org.glassfish.grizzly.http.server.HttpServer;
import org.glassfish.jersey.grizzly2.httpserver.GrizzlyHttpServerFactory;
import org.glassfish.jersey.server.ResourceConfig;
import org.glassfish.jersey.server.ServerProperties;

public class JerseyServerBootstrap extends EmbeddedServerBootstrap {

private HttpServer server;
protected HttpServer server;

public JerseyServerBootstrap() {
setupServer(new JaxrsApplication());
super(new JaxrsApplication());
}

public JerseyServerBootstrap(Application application) {
setupServer(application);
super(application);
}

@Override
public void start() {
try {
server.start();
} catch (IOException e) {
throw new ServerBootstrapException(e);
}
public void stop() {
server.shutdownNow();
}

@Override
protected void startServerInternal() throws Exception {
server.start();
}

private void setupServer(Application application) {
@Override
protected void setupServer(Application application) {
ResourceConfig rc = ResourceConfig.forApplication(application);

Map<String, Object> properties = new HashMap<String, Object>();
Expand All @@ -61,16 +61,11 @@ private void setupServer(Application application) {
int port = Integer.parseInt(serverProperties.getProperty(PORT_PROPERTY));
URI serverUri = UriBuilder.fromPath(ROOT_RESOURCE_PATH).scheme("http").host("localhost").port(port).build();
try {
server = GrizzlyHttpServerFactory.createHttpServer(serverUri, rc);
server = GrizzlyHttpServerFactory.createHttpServer(serverUri, rc, false);
} catch (IllegalArgumentException e) {
throw new ServerBootstrapException(e);
} catch (NullPointerException e) {
throw new ServerBootstrapException(e);
}
}

@Override
public void stop() {
server.shutdownNow();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,29 +17,29 @@
package org.camunda.bpm.engine.rest.util.container;

import java.util.Properties;

import javax.ws.rs.core.Application;

import org.camunda.bpm.engine.rest.util.container.EmbeddedServerBootstrap;
import org.jboss.resteasy.plugins.server.netty.NettyJaxrsServer;

public class ResteasyServerBootstrap extends EmbeddedServerBootstrap {

private NettyJaxrsServer server;
protected NettyJaxrsServer server;

public ResteasyServerBootstrap(Application application) {
setupServer(application);
}

public void start() {
server.start();
super(application);
}

@Override
public void stop() {
server.stop();
}

private void setupServer(Application application) {
@Override
protected void startServerInternal() {
server.start();
}

@Override
protected void setupServer(Application application) {
Properties serverProperties = readProperties();
int port = Integer.parseInt(serverProperties.getProperty(PORT_PROPERTY));

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@
*/
package org.camunda.bpm.engine.rest.util.container;

import org.camunda.bpm.engine.rest.util.container.TomcatServerBootstrap;
import org.jboss.shrinkwrap.api.spec.WebArchive;
import org.jboss.shrinkwrap.resolver.api.maven.PomEquippedResolveStage;
import org.jboss.shrinkwrap.resolver.api.maven.ScopeType;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
/*
* Copyright Camunda Services GmbH and/or licensed to Camunda Services GmbH
* under one or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information regarding copyright
* ownership. Camunda licenses this file to you under the Apache License,
* Version 2.0; you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.camunda.bpm.engine.rest.util.container;

import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;
import org.camunda.bpm.engine.rest.AbstractRestServiceTest;

public abstract class AbstractServerBootstrap {

protected static final String PORT_PROPERTY = "rest.http.port";
protected static final String ROOT_RESOURCE_PATH = "/rest-test";
protected static final String PROPERTIES_FILE = "/testconfig.properties";

protected static final int STARTUP_RETRIES = 3;

public abstract void stop();

public void start() {
startServer(STARTUP_RETRIES);
}

protected abstract void startServer(int startUpRetries);

protected Properties readProperties() {
InputStream propStream = null;
Properties properties = new Properties();

try {
propStream = AbstractRestServiceTest.class.getResourceAsStream(PROPERTIES_FILE);
properties.load(propStream);
} catch (IOException e) {
throw new ServerBootstrapException(e);
} finally {
try {
propStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}

return properties;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,39 +16,37 @@
*/
package org.camunda.bpm.engine.rest.util.container;

import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;
import java.net.BindException;
import javax.ws.rs.core.Application;

import org.camunda.bpm.engine.rest.AbstractRestServiceTest;
public abstract class EmbeddedServerBootstrap extends AbstractServerBootstrap {

public abstract class EmbeddedServerBootstrap {
protected Application application;

protected static final String PORT_PROPERTY = "rest.http.port";
protected static final String ROOT_RESOURCE_PATH = "/rest-test";
private static final String PROPERTIES_FILE = "/testconfig.properties";
protected abstract void setupServer(Application application);
protected abstract void startServerInternal() throws Exception;

public abstract void start();

public abstract void stop();

protected Properties readProperties() {
InputStream propStream = null;
Properties properties = new Properties();
public EmbeddedServerBootstrap(Application application) {
this.application = application;
setupServer(application);
}

@Override
protected void startServer(int startUpRetries) {
try {
propStream = AbstractRestServiceTest.class.getResourceAsStream(PROPERTIES_FILE);
properties.load(propStream);
} catch (IOException e) {
throw new ServerBootstrapException(e);
} finally {
try {
propStream.close();
} catch (IOException e) {
e.printStackTrace();
startServerInternal();
} catch (Exception e) {
if ((e instanceof BindException || e.getCause() instanceof BindException) && startUpRetries > 0) {
stop();
try {
Thread.sleep(500L);
} catch (Exception ex) {
}
setupServer(application);
startServer(--startUpRetries);
} else {
throw new ServerBootstrapException(e);
}
}

return properties;
}
}
Loading

0 comments on commit 6249ebb

Please sign in to comment.