Skip to content

Commit

Permalink
System Maintenance Exception (#462)
Browse files Browse the repository at this point in the history
An exception that may be thrown when the system is in a maintenance state,
such as when the database is being migrated.
  • Loading branch information
krotscheck committed Jul 12, 2018
1 parent ff58614 commit 8b71eb4
Show file tree
Hide file tree
Showing 5 changed files with 243 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
import net.krotscheck.kangaroo.common.exception.mapper.JerseyExceptionMapper;
import net.krotscheck.kangaroo.common.exception.mapper.JsonParseExceptionMapper;
import net.krotscheck.kangaroo.common.exception.mapper.KangarooExceptionMapper;
import net.krotscheck.kangaroo.common.exception.mapper.SystemMaintenanceExceptionMapper;
import net.krotscheck.kangaroo.common.exception.mapper.UnhandledExceptionMapper;

import javax.ws.rs.core.Feature;
Expand All @@ -42,6 +43,7 @@ public final class ExceptionFeature implements Feature {
public boolean configure(final FeatureContext context) {

// Exception mappers.
context.register(new SystemMaintenanceExceptionMapper.Binder());
context.register(new KangarooExceptionMapper.Binder());
context.register(new JerseyExceptionMapper.Binder());
context.register(new JsonParseExceptionMapper.Binder());
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
/*
* Copyright (c) 2018 Michael Krotscheck
*
* Licensed under the Apache License, Version 2.0 (the "License"); 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 net.krotscheck.kangaroo.common.exception;

import javax.ws.rs.core.Response.Status;

/**
* Throw this exception if you detect that the system is in some form of a
* blocking maintenance cycle. The paired exception mapper should also add
* the retry header.
*
* @author Michael Krotscheck
*/
public final class SystemMaintenanceException extends KangarooException {

/**
* Error code for this exception.
*/
public static final ErrorCode CODE = new ErrorCode(
Status.SERVICE_UNAVAILABLE,
"maintenance",
"The system is in maintenance, please try again later.");

/**
* Create a new exception with the specified error code.
*/
public SystemMaintenanceException() {
super(CODE);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
/*
* Copyright (c) 2018 Michael Krotscheck
*
* Licensed under the Apache License, Version 2.0 (the "License"); 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 net.krotscheck.kangaroo.common.exception.mapper;

import net.krotscheck.kangaroo.common.exception.ErrorResponseBuilder;
import net.krotscheck.kangaroo.common.exception.SystemMaintenanceException;
import org.glassfish.jersey.internal.inject.AbstractBinder;

import javax.inject.Singleton;
import javax.ws.rs.core.HttpHeaders;
import javax.ws.rs.core.Response;
import javax.ws.rs.ext.ExceptionMapper;
import javax.ws.rs.ext.Provider;

/**
* Exception mapper for the system's maintenance mode. Maintenance retry is
* set at one minute.
*
* @author Michael Krotscheck
*/
@Provider
public final class SystemMaintenanceExceptionMapper
implements ExceptionMapper<SystemMaintenanceException> {

/**
* Convert to response.
*
* @param e The exceptions to handle.
* @return The Response instance for this error.
*/
public Response toResponse(final SystemMaintenanceException e) {
// Retry after 2 minutes.
return ErrorResponseBuilder
.from(e)
.addHeader(HttpHeaders.RETRY_AFTER, "60")
.build();

}

/**
* HK2 Binder for our injector context.
*/
public static final class Binder extends AbstractBinder {

@Override
protected void configure() {
bind(SystemMaintenanceExceptionMapper.class)
.to(ExceptionMapper.class)
.in(Singleton.class);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
/*
* Copyright (c) 2018 Michael Krotscheck
*
* Licensed under the Apache License, Version 2.0 (the "License"); 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 net.krotscheck.kangaroo.common.exception;

import net.krotscheck.kangaroo.common.exception.ErrorResponseBuilder.ErrorResponse;
import org.junit.Test;

import javax.ws.rs.core.Response.Status;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;

/**
* Test for the system maintenance exception.
*
* @author Michael Krotscheck
*/
public final class SystemMaintenanceExceptionTest {

/**
* Test the type.
*/
@Test
public void testExtendsKangarooException() {
SystemMaintenanceException e = new SystemMaintenanceException();
assertTrue(e instanceof KangarooException);
}

/**
* Test the message.
*/
@Test
public void testCustomMessage() {
SystemMaintenanceException e = new SystemMaintenanceException();
assertEquals(e.getMessage(),
SystemMaintenanceException.CODE.getError());
}

/**
* Test serialization.
*/
@Test
public void testSerialization() {
ErrorResponse e = ErrorResponseBuilder
.from(new SystemMaintenanceException())
.buildEntity();

assertEquals(SystemMaintenanceException.CODE.getErrorDescription(),
e.getErrorDescription());
assertEquals(Status.SERVICE_UNAVAILABLE, e.getHttpStatus());
assertEquals(SystemMaintenanceException.CODE.getError(), e.getError());
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
/*
* Copyright (c) 2018 Michael Krotscheck
*
* Licensed under the Apache License, Version 2.0 (the "License"); 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 net.krotscheck.kangaroo.common.exception.mapper;

import net.krotscheck.kangaroo.common.exception.ErrorResponseBuilder.ErrorResponse;
import net.krotscheck.kangaroo.common.exception.SystemMaintenanceException;
import org.junit.Test;

import javax.ws.rs.core.Response;
import javax.ws.rs.core.Response.Status;

import static org.junit.Assert.assertEquals;

/**
* Tests for the maintenance exception mapper.
*
* @author Michael Krotscheck
*/
public final class SystemMaintenanceExceptionMapperTest {

/**
* Test converting to a response.
*/
@Test
public void testToResponse() {
SystemMaintenanceExceptionMapper mapper
= new SystemMaintenanceExceptionMapper();
SystemMaintenanceException jpe = new SystemMaintenanceException();

Response r = mapper.toResponse(jpe);
ErrorResponse er = (ErrorResponse) r.getEntity();

assertEquals(Status.SERVICE_UNAVAILABLE.getStatusCode(), r.getStatus());
assertEquals(Status.SERVICE_UNAVAILABLE, er.getHttpStatus());
assertEquals(SystemMaintenanceException.CODE.getError(),
er.getError());
assertEquals(SystemMaintenanceException.CODE.getErrorDescription(),
er.getErrorDescription());
}

}

0 comments on commit 8b71eb4

Please sign in to comment.