DATACMNS-525 - Add KeyValuePersistenceExceptionTranslator, fixing Todos.

Added key/value specific PersistenceExceptionTranslator and use it within KeyValueTemplate. Fixed some todos in JavaDoc and added missing tests. Renamed test class for SimpleKeyValueRepository according to the changed name.

Original pull request: #95.
This commit is contained in:
Christoph Strobl
2014-11-25 12:44:00 +01:00
committed by Oliver Gierke
parent 1f71a28408
commit 52108ed006
7 changed files with 261 additions and 12 deletions

View File

@@ -0,0 +1,54 @@
/*
* Copyright 2014 the original author or authors.
*
* 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 org.springframework.data.keyvalue.core;
import java.util.NoSuchElementException;
import org.springframework.dao.DataAccessException;
import org.springframework.dao.DataRetrievalFailureException;
import org.springframework.dao.support.PersistenceExceptionTranslator;
/**
* Simple {@link PersistenceExceptionTranslator} implementation for key/value stores that converts the given runtime
* exception to an appropriate exception from the {@code org.springframework.dao} hierarchy.
*
* @author Christoph Strobl
* @since 1.10
*/
public class KeyValuePersistenceExceptionTranslator implements PersistenceExceptionTranslator {
/*
* (non-Javadoc)
* @see org.springframework.dao.support.PersistenceExceptionTranslator#translateExceptionIfPossible(java.lang.RuntimeException)
*/
@Override
public DataAccessException translateExceptionIfPossible(RuntimeException e) {
if (e == null || e instanceof DataAccessException) {
return (DataAccessException) e;
}
if (e instanceof NoSuchElementException || e instanceof IndexOutOfBoundsException
|| e instanceof IllegalStateException) {
return new DataRetrievalFailureException(e.getMessage(), e);
}
if (e.getClass().getName().startsWith("java")) {
return new UncategorizedKeyValueException(e.getMessage(), e);
}
return null;
}
}

View File

@@ -23,7 +23,9 @@ import java.util.Collection;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;
import org.springframework.dao.DataAccessException;
import org.springframework.dao.InvalidDataAccessApiUsageException;
import org.springframework.dao.support.PersistenceExceptionTranslator;
import org.springframework.data.domain.Sort;
import org.springframework.data.keyvalue.core.mapping.context.KeyValueMappingContext;
import org.springframework.data.keyvalue.core.query.KeyValueQuery;
@@ -43,10 +45,13 @@ import org.springframework.util.StringUtils;
*/
public class KeyValueTemplate implements KeyValueOperations {
private static final PersistenceExceptionTranslator DEFAULT_PERSISTENCE_EXCEPTION_TRANSLATOR = new KeyValuePersistenceExceptionTranslator();
private final KeyValueAdapter adapter;
private final ConcurrentHashMap<Class<?>, String> keySpaceCache = new ConcurrentHashMap<Class<?>, String>();
private final MappingContext<? extends PersistentEntity<?, ? extends PersistentProperty<?>>, ? extends PersistentProperty<?>> mappingContext;
private final IdentifierGenerator identifierGenerator;
private PersistenceExceptionTranslator exceptionTranslator = DEFAULT_PERSISTENCE_EXCEPTION_TRANSLATOR;
/**
* Create new {@link KeyValueTemplate} using the given {@link KeyValueAdapter} with a default
@@ -299,9 +304,7 @@ public class KeyValueTemplate implements KeyValueOperations {
try {
return action.doInKeyValue(this.adapter);
} catch (RuntimeException e) {
// TODO: Use PersistenceExceptionTranslator to translate exception
throw e;
throw resolveExceptionIfPossible(e);
}
}
@@ -401,6 +404,17 @@ public class KeyValueTemplate implements KeyValueOperations {
this.adapter.clear();
}
/**
* Set the {@link PersistenceExceptionTranslator} used for converting {@link RuntimeException}.
*
* @param exceptionTranslator must not be {@literal null}.
*/
public void setExceptionTranslator(PersistenceExceptionTranslator exceptionTranslator) {
Assert.notNull(exceptionTranslator, "ExceptionTranslator must not be null.");
this.exceptionTranslator = exceptionTranslator;
}
protected String resolveKeySpace(Class<?> type) {
Class<?> userClass = ClassUtils.getUserClass(type);
@@ -429,4 +443,10 @@ public class KeyValueTemplate implements KeyValueOperations {
private static boolean typeCheck(Class<?> requiredType, Object candidate) {
return candidate == null ? true : ClassUtils.isAssignable(requiredType, candidate.getClass());
}
private RuntimeException resolveExceptionIfPossible(RuntimeException e) {
DataAccessException translatedException = exceptionTranslator.translateExceptionIfPossible(e);
return translatedException != null ? translatedException : e;
}
}

View File

@@ -0,0 +1,31 @@
/*
* Copyright 2014 the original author or authors.
*
* 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 org.springframework.data.keyvalue.core;
import org.springframework.dao.UncategorizedDataAccessException;
/**
* @author Christoph Strobl
* @since 1.10
*/
public class UncategorizedKeyValueException extends UncategorizedDataAccessException {
private static final long serialVersionUID = -8087116071859122297L;
public UncategorizedKeyValueException(String msg, Throwable cause) {
super(msg, cause);
}
}

View File

@@ -72,15 +72,15 @@ public class SimpleKeyValueRepository<T, ID extends Serializable> implements Key
@Override
public Page<T> findAll(Pageable pageable) {
if (pageable == null) {
List<T> result = findAll();
return new PageImpl<T>(result, null, result.size());
}
List<T> content = null;
// TODO: do we need that guard? Can't findInRange(…) be able to deal with null sorts?
if (pageable.getSort() != null) {
content = operations.findInRange(pageable.getOffset(), pageable.getPageSize(), pageable.getSort(),
entityInformation.getJavaType());
} else {
content = operations.findInRange(pageable.getOffset(), pageable.getPageSize(), entityInformation.getJavaType());
}
content = operations.findInRange(pageable.getOffset(), pageable.getPageSize(), pageable.getSort(),
entityInformation.getJavaType());
return new PageImpl<T>(content, pageable, this.operations.count(entityInformation.getJavaType()));
}