Author: hlship
Date: Tue Feb 13 10:35:46 2007
New Revision: 507150
URL: http://svn.apache.org/viewvc?view=rev&rev=507150
Log:
Improve exception reporting when a type coercion fails, to identify the exact
chain of coercions used
Modified:
tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/internal/services/CompoundCoercion.java
tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/internal/services/ServiceMessages.java
tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/internal/services/TypeCoercerImpl.java
tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/services/CoercionTuple.java
tapestry/tapestry5/tapestry-ioc/trunk/src/main/resources/org/apache/tapestry/ioc/internal/services/ServiceStrings.properties
tapestry/tapestry5/tapestry-ioc/trunk/src/test/java/org/apache/tapestry/ioc/internal/services/TypeCoercerImplTest.java
Modified:
tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/internal/services/CompoundCoercion.java
URL:
http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/internal/services/CompoundCoercion.java?view=diff&rev=507150&r1=507149&r2=507150
==============================================================================
---
tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/internal/services/CompoundCoercion.java
(original)
+++
tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/internal/services/CompoundCoercion.java
Tue Feb 13 10:35:46 2007
@@ -1,4 +1,4 @@
-// Copyright 2006 The Apache Software Foundation
+// Copyright 2006, 2007 The Apache Software Foundation
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -12,44 +12,45 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-package org.apache.tapestry.ioc.internal.services;
-
-import org.apache.tapestry.ioc.services.Coercion;
-
-/**
- * Combines two coercions to create a coercsion through an intermediate type.
- *
- *
- * @param <S>
- * The source (input) type
- * @param <I>
- * The intermediate type
- * @param <T>
- * The target (output) type
- */
-public class CompoundCoercion<S, I, T> implements Coercion<S, T>
-{
- private final Coercion<S, I> _op1;
-
- private final Coercion<I, T> _op2;
-
- public CompoundCoercion(Coercion<S, I> op1, Coercion<I, T> op2)
- {
- _op1 = op1;
- _op2 = op2;
- }
-
- public T coerce(S input)
- {
- // Run the input through the first operation (S --> I), then run the
result of that through
- // the second operation (I --> T).
-
- return _op2.coerce(_op1.coerce(input));
- }
-
- @Override
- public String toString()
- {
- return String.format("CompoundCoercion[%s %s]", _op1, _op2);
- }
-}
+package org.apache.tapestry.ioc.internal.services;
+
+import org.apache.tapestry.ioc.services.Coercion;
+
+/**
+ * Combines two coercions to create a coercsion through an intermediate type.
+ *
+ * @param <S>
+ * The source (input) type
+ * @param <I>
+ * The intermediate type
+ * @param <T>
+ * The target (output) type
+ */
+public class CompoundCoercion<S, I, T> implements Coercion<S, T>
+{
+ private final Coercion<S, I> _op1;
+
+ private final Coercion<I, T> _op2;
+
+ public CompoundCoercion(Coercion<S, I> op1, Coercion<I, T> op2)
+ {
+ _op1 = op1;
+ _op2 = op2;
+ }
+
+ public T coerce(S input)
+ {
+ // Run the input through the first operation (S --> I), then run the
result of that through
+ // the second operation (I --> T).
+
+ I intermediate = _op1.coerce(input);
+
+ return _op2.coerce(intermediate);
+ }
+
+ @Override
+ public String toString()
+ {
+ return String.format("%s, %s", _op1, _op2);
+ }
+}
Modified:
tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/internal/services/ServiceMessages.java
URL:
http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/internal/services/ServiceMessages.java?view=diff&rev=507150&r1=507149&r2=507150
==============================================================================
---
tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/internal/services/ServiceMessages.java
(original)
+++
tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/internal/services/ServiceMessages.java
Tue Feb 13 10:35:46 2007
@@ -1,4 +1,4 @@
-// Copyright 2006 The Apache Software Foundation
+// Copyright 2006, 2007 The Apache Software Foundation
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -18,6 +18,8 @@
import org.apache.tapestry.ioc.Messages;
import org.apache.tapestry.ioc.internal.util.MessagesImpl;
+import org.apache.tapestry.ioc.services.ClassFabUtils;
+import org.apache.tapestry.ioc.services.Coercion;
import org.apache.tapestry.ioc.services.MethodSignature;
import org.apache.tapestry.ioc.services.ThreadCleanupListener;
@@ -167,5 +169,11 @@
static String missingSymbolCloseBraceInPath(String input, String path)
{
return MESSAGES.format("missing-symbol-close-brace-in-path", input,
path);
+ }
+
+ static String failedCoercion(Object input, Class targetType, Coercion
coercion, Throwable cause)
+ {
+ return MESSAGES.format("failed-coercion", String.valueOf(input),
ClassFabUtils
+ .getJavaClassName(targetType), coercion, cause);
}
}
Modified:
tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/internal/services/TypeCoercerImpl.java
URL:
http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/internal/services/TypeCoercerImpl.java?view=diff&rev=507150&r1=507149&r2=507150
==============================================================================
---
tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/internal/services/TypeCoercerImpl.java
(original)
+++
tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/internal/services/TypeCoercerImpl.java
Tue Feb 13 10:35:46 2007
@@ -1,4 +1,4 @@
-// Copyright 2006 The Apache Software Foundation
+// Copyright 2006, 2007 The Apache Software Foundation
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -101,6 +101,8 @@
}
}
+ @SuppressWarnings(
+ { "unchecked", "unchecked" })
private void addTuple(Class key, CoercionTuple tuple)
{
List<CoercionTuple> list = _sourceTypeToTuple.get(key);
@@ -133,16 +135,29 @@
if (effectiveTargetType.isAssignableFrom(sourceType)) return input;
- Coercion coercer = findCoercer(sourceType, effectiveTargetType);
+ Coercion coercion = findCoercion(sourceType, effectiveTargetType);
- Object result = coercer.coerce(input);
+ Object result;
+
+ try
+ {
+ result = coercion.coerce(input);
+ }
+ catch (Exception ex)
+ {
+ throw new RuntimeException(ServiceMessages.failedCoercion(
+ input,
+ targetType,
+ coercion,
+ ex), ex);
+ }
// Double check that the coercer provided a result of the correct type
return effectiveTargetType.cast(result);
}
- private Coercion findCoercer(Class sourceType, Class targetType)
+ private Coercion findCoercion(Class sourceType, Class targetType)
{
CacheKey key = new CacheKey(sourceType, targetType);
@@ -150,7 +165,7 @@
if (result == null)
{
- result = findOrCreateCoercer(sourceType, targetType);
+ result = findOrCreateCoercion(sourceType, targetType);
_cache.put(key, result);
}
@@ -188,7 +203,7 @@
* @return coercer from sourceType to targetType
*/
@SuppressWarnings("unchecked")
- private Coercion findOrCreateCoercer(Class sourceType, Class targetType)
+ private Coercion findOrCreateCoercion(Class sourceType, Class targetType)
{
// These are instance variables because this method may be called
concurrently.
// On a true race, we may go to the work of seeking out and/or
fabricating
@@ -248,13 +263,7 @@
for (List<CoercionTuple> list : _sourceTypeToTuple.values())
{
for (CoercionTuple tuple : list)
- {
- String description = String.format("%s --> %s", ClassFabUtils
- .getJavaClassName(tuple.getSourceType()), ClassFabUtils
- .getJavaClassName(tuple.getTargetType()));
-
- descriptions.add(description);
- }
+ descriptions.add(tuple.toString());
}
return InternalUtils.joinSorted(descriptions);
@@ -329,7 +338,7 @@
tuple.getCoercion());
CoercionTuple compoundTuple = new CoercionTuple(sourceType,
newIntermediateType,
- compoundCoercer);
+ compoundCoercer, false);
// So, every tuple that is added to the queue can take as
input the sourceType.
// The target type may be another intermdiate type, or may be
something
Modified:
tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/services/CoercionTuple.java
URL:
http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/services/CoercionTuple.java?view=diff&rev=507150&r1=507149&r2=507150
==============================================================================
---
tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/services/CoercionTuple.java
(original)
+++
tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/services/CoercionTuple.java
Tue Feb 13 10:35:46 2007
@@ -1,4 +1,4 @@
-// Copyright 2006 The Apache Software Foundation
+// Copyright 2006, 2007 The Apache Software Foundation
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -12,55 +12,107 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-package org.apache.tapestry.ioc.services;
-
-/**
- * An immutable object that represents a mapping from one type to another.
This is also the
- * contribution type when buildign the TypeCoercer service. Wraps a [EMAIL
PROTECTED] Coercion} object that
- * performs the work with additional properties that describe the input and
output types of the
- * coercion, needed when searching for an appropriate coercion (or combination
of coercions).
- *
- *
- * @param <S>
- * source (input) type
- * @param <T>
- * target (output) type
- */
-public final class CoercionTuple<S, T>
-{
- private final Class<S> _sourceType;
-
- private final Class<T> _targetType;
-
- private final Coercion<S, T> _coercion;
-
- public CoercionTuple(Class<S> sourceType, Class<T> targetType, Coercion<S,
T> coercer)
- {
- _sourceType = sourceType;
- _targetType = targetType;
- _coercion = coercer;
- }
-
- @Override
- public String toString()
- {
- return String.format("CoercionTuple[%s --> %s]",
_sourceType.getName(), _targetType
- .getName());
- }
-
- public Coercion<S, T> getCoercion()
- {
- return _coercion;
- }
-
- public Class<S> getSourceType()
- {
- return _sourceType;
- }
-
- public Class<T> getTargetType()
- {
- return _targetType;
- }
-
-}
+package org.apache.tapestry.ioc.services;
+
+import static org.apache.tapestry.ioc.internal.util.Defense.notNull;
+
+/**
+ * An immutable object that represents a mapping from one type to another.
This is also the
+ * contribution type when buildign the TypeCoercer service. Wraps a [EMAIL
PROTECTED] Coercion} object that
+ * performs the work with additional properties that describe the input and
output types of the
+ * coercion, needed when searching for an appropriate coercion (or combination
of coercions).
+ *
+ * @param <S>
+ * source (input) type
+ * @param <T>
+ * target (output) type
+ */
+public final class CoercionTuple<S, T>
+{
+ private final Class<S> _sourceType;
+
+ private final Class<T> _targetType;
+
+ private final Coercion<S, T> _coercion;
+
+ /**
+ * Wraps an arbitrary coercion with an implementation of toString() that
identifies the source
+ * and target types.
+ */
+ private class CoercionWrapper<S, T> implements Coercion<S, T>
+ {
+ private final Coercion<S, T> _coercion;
+
+ public CoercionWrapper(Coercion<S, T> coercion)
+ {
+ _coercion = coercion;
+ }
+
+ public T coerce(S input)
+ {
+ return _coercion.coerce(input);
+ }
+
+ public String toString()
+ {
+ return String.format(
+ "%s --> %s",
+ ClassFabUtils.getJavaClassName(_sourceType),
+ ClassFabUtils.getJavaClassName(_targetType));
+ }
+ }
+
+ /**
+ * Standard constructor, which defaults wrap to true.
+ */
+ public CoercionTuple(Class<S> sourceType, Class<T> targetType, Coercion<S,
T> coercion)
+ {
+ this(sourceType, targetType, coercion, true);
+ }
+
+ /**
+ * Internal-use constructor.
+ *
+ * @param sourceType
+ * the source (or input) type of the coercion
+ * @param targetType
+ * the target (or output) type of the coercion
+ * @param coercion
+ * the object that performs the coercion
+ * @param wrap
+ * if true, the coercion is wrapped to provide a useful
toString()
+ */
+ public CoercionTuple(Class<S> sourceType, Class<T> targetType, Coercion<S,
T> coercion,
+ boolean wrap)
+ {
+ notNull(sourceType, "sourceType");
+ notNull(targetType, "targetType");
+ notNull(coercion, "coercion");
+
+ _sourceType = sourceType;
+ _targetType = targetType;
+ _coercion = wrap ? new CoercionWrapper<S, T>(coercion) : coercion;
+ }
+
+ @Override
+ public String toString()
+ {
+ return _coercion.toString();
+ }
+
+ public Coercion<S, T> getCoercion()
+ {
+ return _coercion;
+ }
+
+ public Class<S> getSourceType()
+ {
+ return _sourceType;
+ }
+
+ public Class<T> getTargetType()
+ {
+ return _targetType;
+ }
+
+}
Modified:
tapestry/tapestry5/tapestry-ioc/trunk/src/main/resources/org/apache/tapestry/ioc/internal/services/ServiceStrings.properties
URL:
http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-ioc/trunk/src/main/resources/org/apache/tapestry/ioc/internal/services/ServiceStrings.properties?view=diff&rev=507150&r1=507149&r2=507150
==============================================================================
---
tapestry/tapestry5/tapestry-ioc/trunk/src/main/resources/org/apache/tapestry/ioc/internal/services/ServiceStrings.properties
(original)
+++
tapestry/tapestry5/tapestry-ioc/trunk/src/main/resources/org/apache/tapestry/ioc/internal/services/ServiceStrings.properties
Tue Feb 13 10:35:46 2007
@@ -1,4 +1,4 @@
-# Copyright 2006 The Apache Software Foundation
+# Copyright 2006, 2007 The Apache Software Foundation
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -37,4 +37,4 @@
symbol-undefined-in-path=Symbol '%s' is not defined (in %s).
missing-symbol-close-brace=Input string '%s' is missing a symbol closing brace.
missing-symbol-close-brace-in-path=Input string '%s' is missing a symbol
closing brace (in %s).
-
+failed-coercion=Coercion of %s to type %s (via %s) failed: %s
Modified:
tapestry/tapestry5/tapestry-ioc/trunk/src/test/java/org/apache/tapestry/ioc/internal/services/TypeCoercerImplTest.java
URL:
http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-ioc/trunk/src/test/java/org/apache/tapestry/ioc/internal/services/TypeCoercerImplTest.java?view=diff&rev=507150&r1=507149&r2=507150
==============================================================================
---
tapestry/tapestry5/tapestry-ioc/trunk/src/test/java/org/apache/tapestry/ioc/internal/services/TypeCoercerImplTest.java
(original)
+++
tapestry/tapestry5/tapestry-ioc/trunk/src/test/java/org/apache/tapestry/ioc/internal/services/TypeCoercerImplTest.java
Tue Feb 13 10:35:46 2007
@@ -1,4 +1,4 @@
-// Copyright 2006 The Apache Software Foundation
+// Copyright 2006, 2007 The Apache Software Foundation
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -87,7 +87,7 @@
}
@Test
- public void coercion_failure()
+ public void no_coercion_found()
{
try
{
@@ -98,6 +98,24 @@
{
assertTrue(ex.getMessage().contains(
"Could not find a coercion from type java.lang.String to
type java.util.Map"));
+ }
+ }
+
+ @Test
+ public void coercion_failure()
+ {
+ try
+ {
+ _coercer.coerce(Collections.EMPTY_MAP, Float.class);
+ unreachable();
+ }
+ catch (RuntimeException ex)
+ {
+ assertTrue(ex
+ .getMessage()
+ .contains(
+ "Coercion of {} to type java.lang.Float (via
java.lang.Object --> java.lang.String, java.lang.String --> java.lang.Double,
java.lang.Double --> java.lang.Float) failed"));
+ assertTrue(ex.getCause() instanceof NumberFormatException);
}
}