Skip to content

Commit

Permalink
Merge pull request #4 from MEITREX/more-repo-utils
Browse files Browse the repository at this point in the history
add more custom exceptions and repository utility
  • Loading branch information
PaulBredl authored Apr 16, 2024
2 parents a0d687e + af32236 commit 13f4ef1
Show file tree
Hide file tree
Showing 5 changed files with 120 additions and 12 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -39,14 +39,17 @@ public static GraphQLError resolveToSingleError(@NonNull final Throwable ex, @No
}

private static ErrorType getErrorType(final Throwable ex) {
// HINT we cannot use switch expressions here because JDK 17 does not support them yet
if (ex instanceof EntityNotFoundException) {
return ErrorType.DataFetchingException;
} else if (ex.getClass().getSimpleName().contains("ValidationException")) {
// special case for validation exceptions since we don't want to add the full graphql dependency
// just for the exception type
if (ex.getClass().getSimpleName().contains("ValidationException")) {
return ErrorType.ValidationError;
}
// HINT add more error types here
return ErrorType.ExecutionAborted;

return switch (ex) {
case EntityNotFoundException ignored -> ErrorType.DataFetchingException;
case ExceptionWithGraphQlErrorType graphQLError -> graphQLError.getErrorType();
default -> ErrorType.ExecutionAborted;
};
}

/**
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package de.unistuttgart.iste.meitrex.common.exception;

import graphql.ErrorType;

/**
* Interface for exceptions that have a {@link ErrorType}.
*/
public interface ExceptionWithGraphQlErrorType {

ErrorType getErrorType();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package de.unistuttgart.iste.meitrex.common.exception;

import graphql.ErrorType;
import jakarta.persistence.EntityNotFoundException;

/**
* Exception that is thrown when a resource is not found.
*/
public class MeitrexNotFoundException extends EntityNotFoundException implements ExceptionWithGraphQlErrorType {
public MeitrexNotFoundException(String entityName, Object id) {
this("Resource " + entityName + " with id " + id + " not found");
}

public MeitrexNotFoundException(String reason) {
super(reason);
}


@Override
public ErrorType getErrorType() {
return ErrorType.DataFetchingException;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package de.unistuttgart.iste.meitrex.common.exception;

import graphql.ErrorType;

/**
* Exception to be thrown when a resource already exists, but it is tried to be created again.
*/
public class ResourceAlreadyExistsException extends RuntimeException implements ExceptionWithGraphQlErrorType {
public ResourceAlreadyExistsException(String reason) {
super(reason);
}

public ResourceAlreadyExistsException(String resourceName, Object id) {
this(resourceName + " with id " + id + " already exists.");
}

public ResourceAlreadyExistsException(Class<?> resourceClass, Object id) {
this(resourceClass.getSimpleName() + " with id " + id + " already exists.");
}

@Override
public ErrorType getErrorType() {
return ErrorType.ValidationError;
}
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
package de.unistuttgart.iste.meitrex.common.persistence;

import de.unistuttgart.iste.meitrex.common.exception.MeitrexNotFoundException;
import de.unistuttgart.iste.meitrex.common.exception.ResourceAlreadyExistsException;
import de.unistuttgart.iste.meitrex.common.util.MeitrexCollectionUtils;
import jakarta.persistence.EntityNotFoundException;
import org.springframework.data.jpa.repository.JpaRepository;

import java.util.ArrayList;
Expand Down Expand Up @@ -32,7 +33,7 @@ default List<T> findAllByIdPreservingOrder(final List<ID> ids) {

/**
* Gets all entities with the given ids and preserves the order of the ids.
* If an entity is not found, an EntityNotFoundException is thrown.
* If an entity is not found, an MeitrexNotFoundException is thrown.
*
* @param ids The ids of the entities to get.
* @return The entities with the given ids in order of the given ids.
Expand All @@ -50,12 +51,57 @@ default List<T> getAllByIdPreservingOrder(final List<ID> ids) {
}

if (!missingIds.isEmpty()) {
throw new EntityNotFoundException("Entities(s) with id(s) "
+ missingIds.stream().map(ID::toString)
.collect(Collectors.joining(", "))
+ " not found");
String missingIdsString = missingIds.stream().map(ID::toString).collect(Collectors.joining(", "));

throw new MeitrexNotFoundException("Entities(s) with id(s) " + missingIdsString + " not found");
}

return allById;
}

/**
* Finds an entity by its id or throws a ResourceNotFoundException if the entity is not found.
* This method is similar to {@link JpaRepository#getReferenceById(Object)},
* but throws a custom MeitrexNotFoundException instead of an EntityNotFoundException.
*
* @param id The id of the entity to find.
* @return The entity with the given id.
* @throws MeitrexNotFoundException If the entity is not found.
*/
default T findByIdOrThrow(final ID id) {
return findById(id).orElseThrow(() -> new MeitrexNotFoundException(getEntityName(), id));
}

/**
* Same as {@link #findByIdOrThrow(Object)}, but depending on the context, the naming
* of this method might be more appropriate.
*
* @see #findByIdOrThrow(Object)
*/
default T requireExists(final ID id) {
return findByIdOrThrow(id);
}

/**
* Checks if an entity with the given id exists and throws an exception if it does.
*
* @param id The id of the entity to check.
* @throws ResourceAlreadyExistsException If the entity exists.
*/
default void requireNotExists(final ID id) {
if (existsById(id)) {
throw new ResourceAlreadyExistsException(getEntityName(), id);
}
}

/**
* Gets the name of the entity for error messages.
* Sub-classes should override this method to provide a name.
* By default, the name is derived from the repository class name.
*
* @return The name of the entity.
*/
default String getEntityName() {
return getClass().getSimpleName().replace("Repository", "");
}
}

0 comments on commit 13f4ef1

Please sign in to comment.