Skip to content

Commit

Permalink
Add options to skip REST resource registration
Browse files Browse the repository at this point in the history
* Add option to skip registration of GotErrorsResource
* Add option to skip registration of ApplicationErrorResource

Closes #289
Closes #290
  • Loading branch information
sleberknight committed Oct 20, 2023
1 parent 4c1aa39 commit 62c1059
Show file tree
Hide file tree
Showing 9 changed files with 161 additions and 12 deletions.
18 changes: 12 additions & 6 deletions src/main/java/org/kiwiproject/dropwizard/error/ErrorContext.java
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,20 @@
* though you can build everything programmatically if you want to.
* <p>
* This acts much like a Dropwizard bundle in that it creates an {@link ApplicationErrorDao} for use anywhere in
* your application, and registers an
* your application, and (by default) registers an
* {@link org.kiwiproject.dropwizard.error.resource.ApplicationErrorResource ApplicationErrorResource} which
* exposes application errors via REST. The {@link #errorDao()} method provides the DAO once an {@link ErrorContext}
* has been built by one of the build methods in {@link ErrorContextBuilder}.
* exposes application errors via REST. By default, it also registers a
* {@link org.kiwiproject.dropwizard.error.resource.GotErrorsResource GotErrorsResource}, which is a REST
* endpoint that can be used to determine if application errors are supported. If you don't want to register
* one or both of these resources, you can disable registration via the {@link ErrorContextBuilder#skipErrorsResource()}
* and {@link ErrorContextBuilder#skipGotErrorsResource()} methods.
* <p>
* It also registers a health check that reports healthy if no errors have occurred in a configurable time window. The
* default value is the last 15 minutes. If desired, you can disable the creation of the health check by calling
* {@link ErrorContextBuilder#skipHealthCheck()} when constructing the instance.
* The {@link #errorDao()} method provides the DAO once an {@link ErrorContext} has been built by one of the
* "build" methods in {@link ErrorContextBuilder}.
* <p>
* This library also registers a health check that reports healthy if no errors have occurred in a configurable time
* window. The default value is the last 15 minutes. If desired, you can disable the creation of the health check by
* calling {@link ErrorContextBuilder#skipHealthCheck()} when constructing the instance.
* <p>
* We currently support storing errors to a relational database with JDBI 3. If your application does not currently
* have a database or uses something else, we also provide several other options including an in-memory H2 database,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,8 @@ public class ErrorContextBuilder {
private ServiceDetails serviceDetails;
private DataStoreType dataStoreType;
private boolean dataStoreTypeAlreadySet;
private boolean addErrorsResource = true;
private boolean addGotErrorsResource = true;
private boolean addHealthCheck = true;
private boolean addCleanupJob = true;
private long timeWindowValue = TimeWindow.DEFAULT_TIME_WINDOW_MINUTES;
Expand Down Expand Up @@ -142,6 +144,28 @@ public ErrorContextBuilder dataStoreType(DataStoreType dataStoreType) {
return this;
}

/**
* Configures the resulting {@link ErrorContext} so that it does not create/register an
* {@link org.kiwiproject.dropwizard.error.resource.ApplicationErrorResource ApplicationErrorResource}.
*
* @return this builder
*/
public ErrorContextBuilder skipErrorsResource() {
this.addErrorsResource = false;
return this;
}

/**
* Configures the resulting {@link ErrorContext} so that it does not create/register a
* {@link org.kiwiproject.dropwizard.error.resource.GotErrorsResource GotErrorsResource}.
*
* @return this builder
*/
public ErrorContextBuilder skipGotErrorsResource() {
this.addGotErrorsResource = false;
return this;
}

/**
* Configures the resulting {@link ErrorContext} so that it does not create/register a health check with Dropwizard.
*
Expand Down Expand Up @@ -316,6 +340,8 @@ private Jdbi3ErrorContext newJdbi3ErrorContext(Jdbi jdbi) {
serviceDetails,
jdbi,
dataStoreType,
addErrorsResource,
addGotErrorsResource,
addHealthCheck,
timeWindowValue,
timeWindowUnit,
Expand Down Expand Up @@ -360,6 +386,8 @@ public ErrorContext buildWithDao(ApplicationErrorDao errorDao) {
serviceDetails,
errorDao,
dataStoreType,
addErrorsResource,
addGotErrorsResource,
addHealthCheck,
timeWindowValue,
timeWindowUnit,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,14 +53,21 @@ static PersistentHostInformation setPersistentHostInformationFrom(ServiceDetails

static void registerResources(Environment environment,
ApplicationErrorDao errorDao,
DataStoreType dataStoreType) {
DataStoreType dataStoreType,
boolean addErrorsResource,
boolean addGotErrorsResource) {

checkArgumentNotNull(environment);
checkArgumentNotNull(errorDao);
checkArgumentNotNull(dataStoreType);

environment.jersey().register(new ApplicationErrorResource(errorDao));
environment.jersey().register(new GotErrorsResource(dataStoreType));
if (addErrorsResource) {
environment.jersey().register(new ApplicationErrorResource(errorDao));
}

if (addGotErrorsResource) {
environment.jersey().register(new GotErrorsResource(dataStoreType));
}
}

static RecentErrorsHealthCheck registerRecentErrorsHealthCheckOrNull(boolean addHealthCheck,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@ class Jdbi3ErrorContext implements ErrorContext {
ServiceDetails serviceDetails,
Jdbi jdbi,
DataStoreType dataStoreType,
boolean addErrorsResource,
boolean addGotErrorsResource,
boolean addHealthCheck,
long timeWindowValue,
TemporalUnit timeWindowUnit,
Expand All @@ -60,7 +62,7 @@ class Jdbi3ErrorContext implements ErrorContext {
addHealthCheck, environment, errorDao, serviceDetails, timeWindowValue, timeWindowUnit);

registerCleanupJobOrNull(addCleanupJob, environment, errorDao, cleanupConfig);
registerResources(environment, errorDao, dataStoreType);
registerResources(environment, errorDao, dataStoreType, addErrorsResource, addGotErrorsResource);
}

private static Jdbi3ApplicationErrorDao getOnDemandErrorDao(Jdbi jdbi) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ public SimpleErrorContext(Environment environment,
ServiceDetails serviceDetails,
ApplicationErrorDao errorDao,
DataStoreType dataStoreType,
boolean addErrorsResource,
boolean addGotErrorsResource,
boolean addHealthCheck,
long timeWindowValue,
TemporalUnit timeWindowUnit,
Expand All @@ -48,7 +50,7 @@ public SimpleErrorContext(Environment environment,
addHealthCheck, environment, errorDao, serviceDetails, timeWindowValue, timeWindowUnit);

registerCleanupJobOrNull(addCleanupJob, environment, errorDao, cleanupConfig);
registerResources(environment, errorDao, dataStoreType);
registerResources(environment, errorDao, dataStoreType, addErrorsResource, addGotErrorsResource);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@

/**
* A simple JAX-RS resource for clients to determine if application errors are available or not.
* It can be used by clients as a generic way to determine whether, for example, a web service
* exposes its application errors.
* <p>
* Clients can check if application errors are available using an HTTP GET request that returns a
* {@code 200 OK} response if available. The response entity contains information on whether the
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.ArgumentMatchers.isA;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoInteractions;
import static org.mockito.Mockito.verifyNoMoreInteractions;
Expand Down Expand Up @@ -137,12 +138,21 @@ void setUp() {

@Test
void shouldRegisterResources() {
ErrorContextUtilities.registerResources(environment, errorDao, DataStoreType.SHARED);
ErrorContextUtilities.registerResources(environment, errorDao, DataStoreType.SHARED, true, true);

verify(jersey).register(isA(ApplicationErrorResource.class));
verify(jersey).register(isA(GotErrorsResource.class));
verifyNoMoreInteractions(jersey);
}

@Test
void shouldNotRegisterResources_WhenTheyAreNotWanted() {
ErrorContextUtilities.registerResources(environment, errorDao, DataStoreType.SHARED, false, false);

verify(jersey, never()).register(isA(ApplicationErrorResource.class));
verify(jersey, never()).register(isA(GotErrorsResource.class));
verifyNoMoreInteractions(jersey);
}
}

@Nested
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
import static org.assertj.core.api.Assertions.assertThatIllegalStateException;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.ArgumentMatchers.isA;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoInteractions;
import static org.mockito.Mockito.verifyNoMoreInteractions;
Expand All @@ -17,6 +19,8 @@
import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.CsvSource;
import org.kiwiproject.dropwizard.error.config.CleanupConfig;
import org.kiwiproject.dropwizard.error.dao.jdbi3.Jdbi3ApplicationErrorDao;
import org.kiwiproject.dropwizard.error.health.RecentErrorsHealthCheck;
Expand All @@ -29,6 +33,7 @@
import org.kiwiproject.test.h2.H2FileBasedDatabase;
import org.kiwiproject.test.junit.jupiter.H2Database;
import org.kiwiproject.test.junit.jupiter.H2FileBasedDatabaseExtension;
import org.mockito.verification.VerificationMode;

import java.time.temporal.ChronoUnit;

Expand Down Expand Up @@ -137,6 +142,8 @@ private Jdbi3ErrorContext newContextWithHealthCheck(boolean addHealthCheck) {
serviceDetails,
jdbi,
DataStoreType.NOT_SHARED,
true,
true,
addHealthCheck,
timeWindowAmount,
timeWindowUnit,
Expand All @@ -145,4 +152,43 @@ private Jdbi3ErrorContext newContextWithHealthCheck(boolean addHealthCheck) {
);
}
}

@Nested
class Resources {

@ParameterizedTest
@CsvSource(textBlock = """
true, true
true, false
false, true,
false, false
""")
void shouldOptionallyRegisterResources(boolean addErrorsResource, boolean addGotErrorsResource) {
newContextWithAddResourceOptionsOf(addErrorsResource, addGotErrorsResource);

var jersey = environment.jersey();
verify(jersey, timesExpected(addErrorsResource)).register(isA(ApplicationErrorResource.class));
verify(jersey, timesExpected(addGotErrorsResource)).register(isA(GotErrorsResource.class));
verifyNoMoreInteractions(jersey);
}

private VerificationMode timesExpected(boolean addResource) {
return addResource ? times(2) : never();
}

private Jdbi3ErrorContext newContextWithAddResourceOptionsOf(boolean addErrorsResource,
boolean addGotErrorsResource) {
return new Jdbi3ErrorContext(environment,
serviceDetails,
jdbi,
DataStoreType.NOT_SHARED,
addErrorsResource,
addGotErrorsResource,
true,
timeWindowAmount,
timeWindowUnit,
false,
new CleanupConfig());
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.ArgumentMatchers.isA;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoInteractions;
import static org.mockito.Mockito.verifyNoMoreInteractions;
Expand All @@ -13,6 +15,8 @@
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.CsvSource;
import org.kiwiproject.dropwizard.error.config.CleanupConfig;
import org.kiwiproject.dropwizard.error.dao.ApplicationErrorDao;
import org.kiwiproject.dropwizard.error.dao.jdk.NoOpApplicationErrorDao;
Expand All @@ -23,6 +27,7 @@
import org.kiwiproject.dropwizard.error.resource.ApplicationErrorResource;
import org.kiwiproject.dropwizard.error.resource.GotErrorsResource;
import org.kiwiproject.test.dropwizard.mockito.DropwizardMockitoMocks;
import org.mockito.verification.VerificationMode;

import java.time.temporal.ChronoUnit;

Expand Down Expand Up @@ -113,11 +118,52 @@ private SimpleErrorContext newContextWithAddHealthCheckOf(boolean addHealthCheck
serviceDetails,
errorDao,
dataStoreType,
true,
true,
addHealthCheck,
timeWindowAmount,
timeWindowUnit,
false,
new CleanupConfig()
);
}

@Nested
class Resources {

@ParameterizedTest
@CsvSource(textBlock = """
true, true
true, false
false, true,
false, false
""")
void shouldOptionallyRegisterResources(boolean addErrorsResource, boolean addGotErrorsResource) {
newContextWithAddResourceOptionsOf(addErrorsResource, addGotErrorsResource);

var jersey = environment.jersey();
verify(jersey, timesExpected(addErrorsResource)).register(isA(ApplicationErrorResource.class));
verify(jersey, timesExpected(addGotErrorsResource)).register(isA(GotErrorsResource.class));
verifyNoMoreInteractions(jersey);
}

private VerificationMode timesExpected(boolean addResource) {
return addResource ? times(1) : never();
}
}

private SimpleErrorContext newContextWithAddResourceOptionsOf(boolean addErrorsResource,
boolean addGotErrorsResource) {
return new SimpleErrorContext(environment,
serviceDetails,
errorDao,
dataStoreType,
addErrorsResource,
addGotErrorsResource,
true,
timeWindowAmount,
timeWindowUnit,
false,
new CleanupConfig());
}
}

0 comments on commit 62c1059

Please sign in to comment.