You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sling.apache.org by ju...@apache.org on 2014/10/03 20:09:32 UTC
svn commit: r1629277 - in /sling/trunk/bundles/extensions/models:
api/src/main/java/org/apache/sling/models/factory/
impl/src/main/java/org/apache/sling/models/impl/
impl/src/test/java/org/apache/sling/models/impl/
impl/src/test/java/org/apache/sling/m...
Author: justin
Date: Fri Oct 3 18:09:32 2014
New Revision: 1629277
URL: http://svn.apache.org/r1629277
Log:
SLING-3709 - adding additional testing for missing elements and post construct failures
Added:
sling/trunk/bundles/extensions/models/impl/src/test/java/org/apache/sling/models/testmodels/classes/FailingPostConstuctModel.java
- copied, changed from r1629167, sling/trunk/bundles/extensions/models/api/src/main/java/org/apache/sling/models/factory/InvalidAdaptableException.java
Modified:
sling/trunk/bundles/extensions/models/api/src/main/java/org/apache/sling/models/factory/InvalidAdaptableException.java
sling/trunk/bundles/extensions/models/api/src/main/java/org/apache/sling/models/factory/InvalidModelException.java
sling/trunk/bundles/extensions/models/api/src/main/java/org/apache/sling/models/factory/MissingElementsException.java
sling/trunk/bundles/extensions/models/impl/src/main/java/org/apache/sling/models/impl/ModelAdapterFactory.java
sling/trunk/bundles/extensions/models/impl/src/main/java/org/apache/sling/models/impl/Result.java
sling/trunk/bundles/extensions/models/impl/src/test/java/org/apache/sling/models/impl/PostConstructTest.java
sling/trunk/bundles/extensions/models/impl/src/test/java/org/apache/sling/models/impl/ResourceModelClassesTest.java
Modified: sling/trunk/bundles/extensions/models/api/src/main/java/org/apache/sling/models/factory/InvalidAdaptableException.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/extensions/models/api/src/main/java/org/apache/sling/models/factory/InvalidAdaptableException.java?rev=1629277&r1=1629276&r2=1629277&view=diff
==============================================================================
--- sling/trunk/bundles/extensions/models/api/src/main/java/org/apache/sling/models/factory/InvalidAdaptableException.java (original)
+++ sling/trunk/bundles/extensions/models/api/src/main/java/org/apache/sling/models/factory/InvalidAdaptableException.java Fri Oct 3 18:09:32 2014
@@ -25,7 +25,7 @@ package org.apache.sling.models.factory;
* @see ModelFactory
*
*/
-public class InvalidAdaptableException extends RuntimeException {
+public final class InvalidAdaptableException extends RuntimeException {
private static final long serialVersionUID = -1209301268928038702L;
public InvalidAdaptableException(String message) {
Modified: sling/trunk/bundles/extensions/models/api/src/main/java/org/apache/sling/models/factory/InvalidModelException.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/extensions/models/api/src/main/java/org/apache/sling/models/factory/InvalidModelException.java?rev=1629277&r1=1629276&r2=1629277&view=diff
==============================================================================
--- sling/trunk/bundles/extensions/models/api/src/main/java/org/apache/sling/models/factory/InvalidModelException.java (original)
+++ sling/trunk/bundles/extensions/models/api/src/main/java/org/apache/sling/models/factory/InvalidModelException.java Fri Oct 3 18:09:32 2014
@@ -25,7 +25,7 @@ package org.apache.sling.models.factory;
*
* @see ModelFactory
*/
-public class InvalidModelException extends RuntimeException {
+public final class InvalidModelException extends RuntimeException {
private static final long serialVersionUID = 4323592065808565135L;
Modified: sling/trunk/bundles/extensions/models/api/src/main/java/org/apache/sling/models/factory/MissingElementsException.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/extensions/models/api/src/main/java/org/apache/sling/models/factory/MissingElementsException.java?rev=1629277&r1=1629276&r2=1629277&view=diff
==============================================================================
--- sling/trunk/bundles/extensions/models/api/src/main/java/org/apache/sling/models/factory/MissingElementsException.java (original)
+++ sling/trunk/bundles/extensions/models/api/src/main/java/org/apache/sling/models/factory/MissingElementsException.java Fri Oct 3 18:09:32 2014
@@ -21,7 +21,6 @@ package org.apache.sling.models.factory;
import java.lang.reflect.AnnotatedElement;
import java.util.Collection;
-
/**
* Exception which is triggered whenever a Sling Model cannot be instantiated
* due to some missing elements (i.e. required fields/methods/constructor params
@@ -30,31 +29,31 @@ import java.util.Collection;
* @see ModelFactory
*
*/
-public class MissingElementsException extends RuntimeException {
+public final class MissingElementsException extends RuntimeException {
private static final long serialVersionUID = 7870762030809272254L;
-
+
private final Collection<? extends AnnotatedElement> missingElements;
private String formatString;
private Class<?> type;
-
+
public MissingElementsException(String format, Collection<? extends AnnotatedElement> elements, Class<?> type) {
super();
this.formatString = format;
this.missingElements = elements;
this.type = type;
}
-
+
@Override
public String getMessage() {
return String.format(formatString, missingElements, type);
}
-
+
public Class<?> getType() {
return type;
}
-
+
public Collection<? extends AnnotatedElement> getMissingElements() {
return missingElements;
}
Modified: sling/trunk/bundles/extensions/models/impl/src/main/java/org/apache/sling/models/impl/ModelAdapterFactory.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/extensions/models/impl/src/main/java/org/apache/sling/models/impl/ModelAdapterFactory.java?rev=1629277&r1=1629276&r2=1629277&view=diff
==============================================================================
--- sling/trunk/bundles/extensions/models/impl/src/main/java/org/apache/sling/models/impl/ModelAdapterFactory.java (original)
+++ sling/trunk/bundles/extensions/models/impl/src/main/java/org/apache/sling/models/impl/ModelAdapterFactory.java Fri Oct 3 18:09:32 2014
@@ -166,7 +166,7 @@ public class ModelAdapterFactory impleme
public <AdapterType> AdapterType getAdapter(Object adaptable, Class<AdapterType> type) {
Result<AdapterType> result = internalCreateModel(adaptable, type);
- result.logFailure(log);
+ result.logFailures(log);
return result.getModel();
}
@@ -174,12 +174,16 @@ public class ModelAdapterFactory impleme
public <ModelType> ModelType createModel(Object adaptable, Class<ModelType> type) throws MissingElementsException,
InvalidAdaptableException, InvalidModelException {
Result<ModelType> result = internalCreateModel(adaptable, type);
- result.throwException();
+ result.throwException(log);
return result.getModel();
}
@Override
public boolean canCreateFromAdaptable(Class<?> modelClass, Object adaptable) throws InvalidModelException {
+ return innerCanCreateFromAdaptable(modelClass, adaptable);
+ }
+
+ private static boolean innerCanCreateFromAdaptable(Class<?> modelClass, Object adaptable) throws InvalidModelException {
Model modelAnnotation = modelClass.getAnnotation(Model.class);
if (modelAnnotation == null) {
throw new InvalidModelException(String.format("Model class '%s' does not have a model annotation", modelClass));
@@ -196,7 +200,11 @@ public class ModelAdapterFactory impleme
@Override
public boolean isModelClass(Class<?> modelClass) {
- return modelClass.getAnnotation(Model.class) != null;
+ return innerIsModelClass(modelClass);
+ }
+
+ private static boolean innerIsModelClass(Class<?> clazz) {
+ return clazz.getAnnotation(Model.class) != null;
}
@SuppressWarnings("unchecked")
@@ -206,7 +214,7 @@ public class ModelAdapterFactory impleme
if (threadInvocationCounter.isMaximumReached()) {
String msg = String.format("Adapting %s to %s failed, too much recursive invocations (>=%s).",
new Object[] { adaptable, type, threadInvocationCounter.maxRecursionDepth });
- result.setFailure(FailureType.OTHER, msg);
+ result.addFailure(FailureType.OTHER, msg);
return result;
};
threadInvocationCounter.increase();
@@ -216,11 +224,10 @@ public class ModelAdapterFactory impleme
if (implementationType != null) {
type = (Class<ModelType>) implementationType;
}
- result.setType(type);
Model modelAnnotation = type.getAnnotation(Model.class);
if (modelAnnotation == null) {
- result.setFailure(FailureType.NO_MODEL_ANNOTATION);
+ result.addFailure(FailureType.NO_MODEL_ANNOTATION, type);
return result;
}
boolean isAdaptable = false;
@@ -232,7 +239,7 @@ public class ModelAdapterFactory impleme
}
}
if (!isAdaptable) {
- result.setFailure(FailureType.ADAPTABLE_DOES_NOT_MATCH);
+ result.addFailure(FailureType.ADAPTABLE_DOES_NOT_MATCH, type);
} else if (type.isInterface()) {
InvocationHandler handler = createInvocationHandler(adaptable, type, modelAnnotation, result);
if (handler != null) {
@@ -245,7 +252,7 @@ public class ModelAdapterFactory impleme
result.setModel(model);
return result;
} catch (Exception e) {
- result.setFailure(FailureType.OTHER, "Unable to create object", e);
+ result.addFailure(FailureType.OTHER, "Unable to create object", e);
}
}
return result;
@@ -293,12 +300,13 @@ public class ModelAdapterFactory impleme
* Is called each time when the given value should be injected into the given element
* @param element
* @param value
+ * @param result
* @return true if injection was successful otherwise false
*/
- public boolean inject(AnnotatedElement element, Object value);
+ public boolean inject(AnnotatedElement element, Object value, Result<?> result);
}
- private static class SetFieldCallback implements InjectCallback {
+ private class SetFieldCallback implements InjectCallback {
private final Object object;
@@ -307,12 +315,12 @@ public class ModelAdapterFactory impleme
}
@Override
- public boolean inject(AnnotatedElement element, Object value) {
- return setField((Field) element, object, value);
+ public boolean inject(AnnotatedElement element, Object value, Result<?> result) {
+ return setField((Field) element, object, value, result);
}
}
- private static class SetMethodsCallback implements InjectCallback {
+ private class SetMethodsCallback implements InjectCallback {
private final Map<Method, Object> methods;
@@ -321,12 +329,12 @@ public class ModelAdapterFactory impleme
}
@Override
- public boolean inject(AnnotatedElement element, Object value) {
- return setMethod((Method) element, methods, value);
+ public boolean inject(AnnotatedElement element, Object value, Result<?> result) {
+ return setMethod((Method) element, methods, value, result);
}
}
- private static class SetConstructorParameterCallback implements InjectCallback {
+ private class SetConstructorParameterCallback implements InjectCallback {
private final List<Object> parameterValues;
@@ -335,14 +343,14 @@ public class ModelAdapterFactory impleme
}
@Override
- public boolean inject(AnnotatedElement element, Object value) {
- return setConstructorParameter((ConstructorParameter)element, parameterValues, value);
+ public boolean inject(AnnotatedElement element, Object value, Result<?> result) {
+ return setConstructorParameter((ConstructorParameter)element, parameterValues, value, result);
}
}
private boolean injectElement(final AnnotatedElement element, final Object adaptable, final Type type,
final boolean injectPrimitiveInitialValue, final Model modelAnnotation, final DisposalCallbackRegistry registry,
- final InjectCallback callback) {
+ final InjectCallback callback, Result<?> result) {
InjectAnnotationProcessor annotationProcessor = null;
String source = getSource(element);
@@ -365,7 +373,7 @@ public class ModelAdapterFactory impleme
if (source == null || source.equals(injector.getName())) {
if (name != null || injector instanceof AcceptsNullName) {
Object value = injector.getValue(injectionAdaptable, name, type, element, registry);
- if (callback.inject(element, value)) {
+ if (callback.inject(element, value, result)) {
wasInjectionSuccessful = true;
break;
}
@@ -375,14 +383,14 @@ public class ModelAdapterFactory impleme
}
// if injection failed, use default
if (!wasInjectionSuccessful) {
- wasInjectionSuccessful = injectDefaultValue(element, type, annotationProcessor, callback);
+ wasInjectionSuccessful = injectDefaultValue(element, type, annotationProcessor, callback, result);
}
// if default is not set, check if mandatory
if (!wasInjectionSuccessful) {
if (isOptional(element, modelAnnotation, annotationProcessor)) {
if (injectPrimitiveInitialValue) {
- injectPrimitiveInitialValue(element, type, callback);
+ injectPrimitiveInitialValue(element, type, callback, result);
}
} else {
return false;
@@ -409,13 +417,13 @@ public class ModelAdapterFactory impleme
if (returnType != genericReturnType) {
isPrimitive = true;
}
- if (!injectElement(method, adaptable, returnType, isPrimitive, modelAnnotation, registry, callback)) {
+ if (!injectElement(method, adaptable, returnType, isPrimitive, modelAnnotation, registry, callback, result)) {
requiredMethods.add(method);
}
}
registry.seal();
if (!requiredMethods.isEmpty()) {
- result.setFailure(FailureType.MISSING_METHODS, requiredMethods);
+ result.addFailure(FailureType.MISSING_METHODS, requiredMethods, type);
return null;
}
return handler;
@@ -464,7 +472,7 @@ public class ModelAdapterFactory impleme
Constructor<ModelType> constructorToUse = getBestMatchingConstructor(adaptable, type);
if (constructorToUse == null) {
- result.setFailure(FailureType.NO_USABLE_CONSTRUCTOR);
+ result.addFailure(FailureType.NO_USABLE_CONSTRUCTOR, type);
return null;
}
@@ -502,21 +510,24 @@ public class ModelAdapterFactory impleme
Set<Field> injectableFields = collectInjectableFields(type);
for (Field field : injectableFields) {
Type fieldType = mapPrimitiveClasses(field.getGenericType());
- if (!injectElement(field, adaptable, fieldType, false, modelAnnotation, registry, callback)) {
+ if (!injectElement(field, adaptable, fieldType, false, modelAnnotation, registry, callback, result)) {
requiredFields.add(field);
}
}
registry.seal();
if (!requiredFields.isEmpty()) {
- result.setFailure(FailureType.MISSING_FIELDS, requiredFields);
+ result.addFailure(FailureType.MISSING_FIELDS, requiredFields, type);
return null;
}
try {
invokePostConstruct(object);
return object;
- } catch (Exception e) {
- result.setFailure(FailureType.FAILED_CALLING_POST_CONSTRUCT, e);
+ } catch (InvocationTargetException e) {
+ result.addFailure(FailureType.FAILED_CALLING_POST_CONSTRUCT, e.getCause());
+ return null;
+ } catch (IllegalAccessException e) {
+ result.addFailure(FailureType.FAILED_CALLING_POST_CONSTRUCT, e);
return null;
}
@@ -575,12 +586,12 @@ public class ModelAdapterFactory impleme
}
ConstructorParameter constructorParameter = new ConstructorParameter(
constructor.getParameterAnnotations()[i], constructor.getParameterTypes()[i], genericType, i);
- if (!injectElement(constructorParameter, adaptable, genericType, isPrimitive, modelAnnotation, registry, callback)) {
+ if (!injectElement(constructorParameter, adaptable, genericType, isPrimitive, modelAnnotation, registry, callback, result)) {
requiredParameters.add(constructorParameter);
}
}
if (!requiredParameters.isEmpty()) {
- result.setFailure(FailureType.MISSING_CONSTRUCTOR_PARAMS, requiredParameters);
+ result.addFailure(FailureType.MISSING_CONSTRUCTOR_PARAMS, requiredParameters, type);
return null;
}
return constructor.newInstance(paramValues.toArray(new Object[paramValues.size()]));
@@ -602,11 +613,11 @@ public class ModelAdapterFactory impleme
}
private boolean injectDefaultValue(AnnotatedElement point, Type type, InjectAnnotationProcessor processor,
- InjectCallback callback) {
+ InjectCallback callback, Result<?> result) {
if (processor != null) {
if (processor.hasDefault()) {
- return callback.inject(point, processor.getDefault());
+ return callback.inject(point, processor.getDefault(), result);
}
}
Default defaultAnnotation = point.getAnnotation(Default.class);
@@ -675,7 +686,7 @@ public class ModelAdapterFactory impleme
log.warn("Cannot provide default for {}", type);
return false;
}
- return callback.inject(point, value);
+ return callback.inject(point, value, result);
}
/**
@@ -685,8 +696,9 @@ public class ModelAdapterFactory impleme
* @param point Annotated element
* @param wrapperType Non-primitive wrapper class for primitive class
* @param callback Inject callback
+ * @param result
*/
- private void injectPrimitiveInitialValue(AnnotatedElement point, Type wrapperType, InjectCallback callback) {
+ private void injectPrimitiveInitialValue(AnnotatedElement point, Type wrapperType, InjectCallback callback, Result<?> result) {
Type primitiveType = mapWrapperClasses(wrapperType);
Object value = null;
if (primitiveType == int.class) {
@@ -707,7 +719,7 @@ public class ModelAdapterFactory impleme
value = Character.valueOf('\u0000');
}
if (value != null) {
- callback.inject(point, value);
+ callback.inject(point, value, result);
};
}
@@ -783,7 +795,7 @@ public class ModelAdapterFactory impleme
return true;
}
- private void invokePostConstruct(Object object) throws Exception {
+ private void invokePostConstruct(Object object) throws InvocationTargetException, IllegalAccessException {
Class<?> clazz = object.getClass();
List<Method> postConstructMethods = new ArrayList<Method>();
while (clazz != null) {
@@ -827,9 +839,9 @@ public class ModelAdapterFactory impleme
}
}
- private static boolean setField(Field field, Object createdObject, Object value) {
+ private boolean setField(Field field, Object createdObject, Object value, Result<?> result) {
if (value != null) {
- value = adaptIfNecessary(value, field.getType(), field.getGenericType());
+ value = adaptIfNecessary(value, field.getType(), field.getGenericType(), result);
// value may now be null due to the adaptation done above
if (value == null) {
return false;
@@ -854,9 +866,9 @@ public class ModelAdapterFactory impleme
}
}
- private static boolean setMethod(Method method, Map<Method, Object> methods, Object value) {
+ private boolean setMethod(Method method, Map<Method, Object> methods, Object value, Result<?> result) {
if (value != null) {
- value = adaptIfNecessary(value, method.getReturnType(), method.getGenericReturnType());
+ value = adaptIfNecessary(value, method.getReturnType(), method.getGenericReturnType(), result);
// value may now be null due to the adaptation done above
if (value == null) {
return false;
@@ -868,9 +880,9 @@ public class ModelAdapterFactory impleme
}
}
- private static boolean setConstructorParameter(ConstructorParameter constructorParameter, List<Object> parameterValues, Object value) {
+ private boolean setConstructorParameter(ConstructorParameter constructorParameter, List<Object> parameterValues, Object value, Result<?> result) {
if (value != null && constructorParameter.getType() instanceof Class<?>) {
- value = adaptIfNecessary(value, (Class<?>) constructorParameter.getType(), constructorParameter.getGenericType());
+ value = adaptIfNecessary(value, (Class<?>) constructorParameter.getType(), constructorParameter.getGenericType(), result);
// value may now be null due to the adaptation done above
if (value == null) {
return false;
@@ -882,10 +894,18 @@ public class ModelAdapterFactory impleme
}
}
- private static Object adaptIfNecessary(Object value, Class<?> type, Type genericType) {
+ private Object adaptIfNecessary(Object value, Class<?> type, Type genericType, Result<?> parentResult) {
if (!isAcceptableType(type, genericType, value)) {
Class<?> declaredType = type;
- if (value instanceof Adaptable) {
+ if (isModelClass(type) && canCreateFromAdaptable(type, value)) {
+ Result<?> result = internalCreateModel(value, type);
+ if (result.getModel() == null) {
+ parentResult.appendFailures(result);
+ value = null;
+ } else {
+ value = result.getModel();
+ }
+ } else if (value instanceof Adaptable) {
value = ((Adaptable) value).adaptTo(type);
} else if (genericType instanceof ParameterizedType) {
ParameterizedType parameterizedType = (ParameterizedType) genericType;
Modified: sling/trunk/bundles/extensions/models/impl/src/main/java/org/apache/sling/models/impl/Result.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/extensions/models/impl/src/main/java/org/apache/sling/models/impl/Result.java?rev=1629277&r1=1629276&r2=1629277&view=diff
==============================================================================
--- sling/trunk/bundles/extensions/models/impl/src/main/java/org/apache/sling/models/impl/Result.java (original)
+++ sling/trunk/bundles/extensions/models/impl/src/main/java/org/apache/sling/models/impl/Result.java Fri Oct 3 18:09:32 2014
@@ -19,6 +19,8 @@
package org.apache.sling.models.impl;
import java.lang.reflect.AnnotatedElement;
+import java.util.ArrayList;
+import java.util.List;
import java.util.Set;
import org.apache.sling.models.factory.InvalidAdaptableException;
@@ -33,9 +35,9 @@ public class Result<ModelType> {
"Failure calling post-construct method"), NO_MODEL_ANNOTATION(
"Provided Adapter class does not have a Model annotation"), NO_USABLE_CONSTRUCTOR(
"Unable to find a useable constructor"), OTHER("Unclassified problem"), MISSING_METHODS(
- "Required methods %s on model interface %s were not able to be injected."), MISSING_FIELDS(
- "Required fields %s on model interface %s were not able to be injected."), MISSING_CONSTRUCTOR_PARAMS(
- "Required constructor parameteres %s on model interface %s were not able to be injected.");
+ "Required methods %s on model %s were not able to be injected."), MISSING_FIELDS(
+ "Required fields %s on model %s were not able to be injected."), MISSING_CONSTRUCTOR_PARAMS(
+ "Required constructor parameteres %s on model %s were not able to be injected.");
private String message;
@@ -43,98 +45,146 @@ public class Result<ModelType> {
this.message = msg;
}
}
+
+ private static class Failure {
+ private FailureType failureType;
- private Exception failureException;
+ private Throwable failureException;
- private String failureMessage;
+ private String failureMessage;
- private FailureType failureType;
+ private Set<? extends AnnotatedElement> missingElements;
- private ModelType model;
+ private Class<?> clazz;
- private Class<? extends ModelType> type;
+ private String getMessage() {
+ if (failureMessage != null) {
+ return failureMessage;
+ } else if (failureType != null) {
+ return failureType.message;
+ } else {
+ return null;
+ }
+ }
- private Set<? extends AnnotatedElement> missingElements;
+ public void log(Logger log) {
- public ModelType getModel() {
- return model;
- }
-
- public void logFailure(Logger log) {
- if (failureType != null) {
- switch (failureType) {
- case MISSING_CONSTRUCTOR_PARAMS:
- case MISSING_FIELDS:
- case MISSING_METHODS:
- log.error(String.format(failureType.message, missingElements, type));
- break;
- default:
- log.error(getMessage(), failureException);
- break;
+ if (failureType != null) {
+ switch (failureType) {
+ case MISSING_CONSTRUCTOR_PARAMS:
+ case MISSING_FIELDS:
+ case MISSING_METHODS:
+ log.error(String.format(failureType.message, missingElements, clazz));
+ break;
+ default:
+ log.error(getMessage(), failureException);
+ break;
+ }
}
}
- }
- public void setFailure(FailureType type) {
- this.failureType = type;
+ public void throwException() {
+ RuntimeException e = null;
+ if (failureType != null) {
+ final String msg = getMessage();
+ switch (failureType) {
+ case ADAPTABLE_DOES_NOT_MATCH:
+ e = new InvalidAdaptableException(msg);
+ break;
+ case FAILED_CALLING_POST_CONSTRUCT:
+ case NO_MODEL_ANNOTATION:
+ case NO_USABLE_CONSTRUCTOR:
+ e = new InvalidModelException(msg);
+ break;
+ case MISSING_CONSTRUCTOR_PARAMS:
+ case MISSING_FIELDS:
+ case MISSING_METHODS:
+ e = new MissingElementsException(failureType.message, missingElements, clazz);
+ break;
+ default:
+ e = new RuntimeException(msg);
+ break;
+ }
+ }
+ if (e != null) {
+ if (failureException != null) {
+ e.initCause(failureException);
+ }
+ throw e;
+ }
+ }
+
}
- public void setFailure(FailureType type, Exception e) {
- this.failureType = type;
- this.failureException = e;
- }
+ private ModelType model;
+
+ private List<Failure> failures = new ArrayList<Failure>();
- public void setFailure(FailureType type, Set<? extends AnnotatedElement> requiredElements) {
- this.failureType = type;
- this.missingElements = requiredElements;
+ public ModelType getModel() {
+ return model;
}
- public void setFailure(FailureType type, String msg) {
- this.failureType = type;
- this.failureMessage = msg;
+ public void logFailures(Logger log) {
+ for (Failure failure : failures) {
+ failure.log(log);
+ }
}
- public void setFailure(FailureType type, String msg, Exception e) {
- this.failureType = type;
- this.failureMessage = msg;
- this.failureException = e;
+ public void addFailure(FailureType type, Class<?> clazz) {
+ Failure f = new Failure();
+ f.failureType = type;
+ f.clazz = clazz;
+ failures.add(f);
+ }
+
+ public void addFailure(FailureType type, Throwable e) {
+ Failure f = new Failure();
+ f.failureType = type;
+ f.failureException = e;
+ failures.add(f);
+ }
+
+ public void addFailure(FailureType type, Set<? extends AnnotatedElement> requiredElements, Class<?> clazz) {
+ Failure f = new Failure();
+ f.failureType = type;
+ f.missingElements = requiredElements;
+ f.clazz = clazz;
+ failures.add(f);
+ }
+
+ public void addFailure(FailureType type, String msg) {
+ Failure f = new Failure();
+ f.failureType = type;
+ f.failureMessage = msg;
+ failures.add(f);
+ }
+
+ public void addFailure(FailureType type, String msg, Throwable e) {
+ Failure f = new Failure();
+ f.failureType = type;
+ f.failureMessage = msg;
+ f.failureException = e;
+ failures.add(f);
}
public void setModel(ModelType model) {
this.model = model;
}
-
+/*
public void setType(Class<? extends ModelType> type) {
this.type = type;
}
-
- public void throwException() {
- if (failureType != null) {
- final String msg = getMessage();
- switch (failureType) {
- case ADAPTABLE_DOES_NOT_MATCH:
- throw new InvalidAdaptableException(msg);
- case FAILED_CALLING_POST_CONSTRUCT:
- case NO_MODEL_ANNOTATION:
- case NO_USABLE_CONSTRUCTOR:
- throw new InvalidModelException(msg);
- case MISSING_CONSTRUCTOR_PARAMS:
- case MISSING_FIELDS:
- case MISSING_METHODS:
- throw new MissingElementsException(failureType.message, missingElements, type);
- case OTHER:
- throw new RuntimeException(msg);
- }
+*/
+ public void throwException(Logger log) {
+ for (int i = 0; i < failures.size() - 1; i++) {
+ failures.get(i).log(log);
+ }
+ if (failures.size() >= 1) {
+ failures.get(failures.size() - 1).throwException();
}
}
- private String getMessage() {
- if (failureMessage != null) {
- return failureMessage;
- } else if (failureType != null) {
- return failureType.message;
- } else {
- return null;
- }
+ public void appendFailures(Result<?> result) {
+ failures.addAll(result.failures);
}
}
Modified: sling/trunk/bundles/extensions/models/impl/src/test/java/org/apache/sling/models/impl/PostConstructTest.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/extensions/models/impl/src/test/java/org/apache/sling/models/impl/PostConstructTest.java?rev=1629277&r1=1629276&r2=1629277&view=diff
==============================================================================
--- sling/trunk/bundles/extensions/models/impl/src/test/java/org/apache/sling/models/impl/PostConstructTest.java (original)
+++ sling/trunk/bundles/extensions/models/impl/src/test/java/org/apache/sling/models/impl/PostConstructTest.java Fri Oct 3 18:09:32 2014
@@ -22,6 +22,8 @@ import static org.mockito.Mockito.*;
import java.util.Hashtable;
import org.apache.sling.api.resource.Resource;
+import org.apache.sling.models.factory.InvalidModelException;
+import org.apache.sling.models.testmodels.classes.FailingPostConstuctModel;
import org.apache.sling.models.testmodels.classes.SubClass;
import org.apache.sling.models.testmodels.classes.SubClassOverriddenPostConstruct;
import org.junit.Before;
@@ -41,33 +43,49 @@ public class PostConstructTest {
@Mock
private BundleContext bundleContext;
+ @Mock
+ private Resource resource;
+
+ ModelAdapterFactory factory = new ModelAdapterFactory();
+
@Before
public void setup() {
when(componentCtx.getBundleContext()).thenReturn(bundleContext);
when(componentCtx.getProperties()).thenReturn(new Hashtable<String, Object>());
+ factory.activate(componentCtx);
+ // no injectors are necessary
}
@Test
public void testClassOrder() {
- Resource r = mock(Resource.class);
- ModelAdapterFactory factory = new ModelAdapterFactory();
- factory.activate(componentCtx);
- // no injectors are necessary
-
- SubClass sc = factory.getAdapter(r, SubClass.class);
+ SubClass sc = factory.getAdapter(resource, SubClass.class);
assertTrue(sc.getPostConstructCalledTimestampInSub() > sc.getPostConstructCalledTimestampInSuper());
assertTrue(sc.getPostConstructCalledTimestampInSuper() > 0);
}
-
+
@Test
public void testOverriddenPostConstruct() {
- Resource r = mock(Resource.class);
- ModelAdapterFactory factory = new ModelAdapterFactory();
- factory.activate(componentCtx);
- // no injectors are necessary
-
- SubClassOverriddenPostConstruct sc = factory.getAdapter(r, SubClassOverriddenPostConstruct.class);
+ SubClassOverriddenPostConstruct sc = factory.getAdapter(resource, SubClassOverriddenPostConstruct.class);
assertEquals("Post construct not called exactly one time in sub class!", 1, sc.getPostConstructorCalledCounter());
assertEquals("Post construct was called on super class although overridden in sub class", 0, sc.getPostConstructCalledTimestampInSuper());
}
+
+ @Test
+ public void testPostConstructMethodWhichThrowsException() {
+ FailingPostConstuctModel model = factory.getAdapter(resource, FailingPostConstuctModel.class);
+ assertNull(model);
+ }
+
+ @Test
+ public void testPostConstructMethodWhichThrowsExceptionThrowingException() {
+ boolean thrown = false;
+ try {
+ factory.createModel(resource, FailingPostConstuctModel.class);
+ } catch (InvalidModelException e) {
+ assertTrue(e.getMessage().contains("post-construct"));
+ assertEquals("FAIL", e.getCause().getMessage());
+ thrown = true;
+ }
+ assertTrue(thrown);
+ }
}
Modified: sling/trunk/bundles/extensions/models/impl/src/test/java/org/apache/sling/models/impl/ResourceModelClassesTest.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/extensions/models/impl/src/test/java/org/apache/sling/models/impl/ResourceModelClassesTest.java?rev=1629277&r1=1629276&r2=1629277&view=diff
==============================================================================
--- sling/trunk/bundles/extensions/models/impl/src/test/java/org/apache/sling/models/impl/ResourceModelClassesTest.java (original)
+++ sling/trunk/bundles/extensions/models/impl/src/test/java/org/apache/sling/models/impl/ResourceModelClassesTest.java Fri Oct 3 18:09:32 2014
@@ -19,6 +19,7 @@ package org.apache.sling.models.impl;
import static org.junit.Assert.*;
import static org.mockito.Mockito.*;
+import java.lang.reflect.Field;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
@@ -29,6 +30,7 @@ import org.apache.commons.lang.RandomStr
import org.apache.sling.api.resource.Resource;
import org.apache.sling.api.resource.ValueMap;
import org.apache.sling.api.wrappers.ValueMapDecorator;
+import org.apache.sling.models.factory.MissingElementsException;
import org.apache.sling.models.impl.injectors.ChildResourceInjector;
import org.apache.sling.models.impl.injectors.ValueMapInjector;
import org.apache.sling.models.testmodels.classes.ArrayPrimitivesModel;
@@ -180,6 +182,29 @@ public class ResourceModelClassesTest {
}
@Test
+ public void testRequiredPropertyModelWithException() {
+ Map<String, Object> map = new HashMap<String, Object>();
+ map.put("first", "first-value");
+ map.put("third", "third-value");
+ ValueMap vm = spy(new ValueMapDecorator(map));
+
+ Resource res = mock(Resource.class);
+ when(res.adaptTo(ValueMap.class)).thenReturn(vm);
+
+ boolean thrown = false;
+ try {
+ factory.createModel(res, ResourceModelWithRequiredField.class);
+ } catch (MissingElementsException e) {
+ assertEquals(ResourceModelWithRequiredField.class, e.getType());
+ assertEquals("required", ((Field) e.getMissingElements().iterator().next()).getName());
+ thrown = true;
+ }
+ assertTrue(thrown);
+
+ verify(vm).get("required", String.class);
+ }
+
+ @Test
public void testRequiredPropertyModelOptionalStrategyAvailable() {
Map<String, Object> map = new HashMap<String, Object>();
map.put("first", "first-value");
Copied: sling/trunk/bundles/extensions/models/impl/src/test/java/org/apache/sling/models/testmodels/classes/FailingPostConstuctModel.java (from r1629167, sling/trunk/bundles/extensions/models/api/src/main/java/org/apache/sling/models/factory/InvalidAdaptableException.java)
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/extensions/models/impl/src/test/java/org/apache/sling/models/testmodels/classes/FailingPostConstuctModel.java?p2=sling/trunk/bundles/extensions/models/impl/src/test/java/org/apache/sling/models/testmodels/classes/FailingPostConstuctModel.java&p1=sling/trunk/bundles/extensions/models/api/src/main/java/org/apache/sling/models/factory/InvalidAdaptableException.java&r1=1629167&r2=1629277&rev=1629277&view=diff
==============================================================================
--- sling/trunk/bundles/extensions/models/api/src/main/java/org/apache/sling/models/factory/InvalidAdaptableException.java (original)
+++ sling/trunk/bundles/extensions/models/impl/src/test/java/org/apache/sling/models/testmodels/classes/FailingPostConstuctModel.java Fri Oct 3 18:09:32 2014
@@ -16,19 +16,19 @@
* specific language governing permissions and limitations
* under the License.
*/
-package org.apache.sling.models.factory;
+package org.apache.sling.models.testmodels.classes;
-/**
- * Exception which is triggered whenever a Sling Model could not be
- * instantiated because it could not be adapted from the given adaptable.
- *
- * @see ModelFactory
- *
- */
-public class InvalidAdaptableException extends RuntimeException {
- private static final long serialVersionUID = -1209301268928038702L;
+import javax.annotation.PostConstruct;
+
+import org.apache.sling.api.resource.Resource;
+import org.apache.sling.models.annotations.Model;
- public InvalidAdaptableException(String message) {
- super(message);
+@Model(adaptables=Resource.class)
+public class FailingPostConstuctModel {
+
+ @PostConstruct
+ protected void pc() throws Exception {
+ throw new Exception("FAIL");
}
+
}