[ 
https://issues.apache.org/jira/browse/TAP5-2688?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=17417128#comment-17417128
 ] 

Ben Weidig commented on TAP5-2688:
----------------------------------

It fails for me with Tapestry 5.6.4, too.

The issue was most likely introduced with JSONArray becoming a "real" 
Collection.
That's why the TypeCoercer doesn't match String->Collection correctly, because 
instead of finding the Object->Collection coercer, it first matches 
String->JSONArray.

The current implementation prefers exact matches, but it tries "good enough" if 
none is found.
String->JSONArray is a valid match for String->Collection, because the source 
types matches and the target type is assignable.

There's a comment in the TypeCoercerImpl code talking about adding a concept of 
"cost" and "quality" of the found Coercer. Cost (fewer intermediate coercions) 
is already implicitly implemented because the cheapest are checked first. But 
there are no optimizations around the quality regarding the target type.

A workaround should be possible by adding coercion tuples for the explicit 
source and target types, so they are matched earlier than the incorrect one.

> TypeCoercer fails to coerce String to Collection since 5.7
> ----------------------------------------------------------
>
>                 Key: TAP5-2688
>                 URL: https://issues.apache.org/jira/browse/TAP5-2688
>             Project: Tapestry 5
>          Issue Type: Bug
>    Affects Versions: 5.7.3
>            Reporter: Yannick Dylla
>            Priority: Major
>
> Hi,
>  with Tapestry 5.7.3 the TypeCoercer fails to coerce String to Collection. 
> With 5.6 this worked fine and produced a single element list.
>  It is probably the fault of JSONArray which now implements Collection.
> When one uses List.class as target for the TypeCoercer the example works fine.
> Example program:
> {code:java}
> import org.apache.tapestry5.commons.services.TypeCoercer;
> import org.apache.tapestry5.ioc.Registry;
> import org.apache.tapestry5.ioc.RegistryBuilder;
> import org.apache.tapestry5.json.modules.JSONModule;
> import java.util.Collection;
> import java.util.List;
> public class TypeCoercerBug {
>   public static void main(String[] args) throws Exception {
>     Registry registry = 
> RegistryBuilder.buildAndStartupRegistry(JSONModule.class);
>     try {
>       TypeCoercer typeCoercer = registry.getService(TypeCoercer.class);
>       List<String> expected = List.of("foo");
>       Object result = typeCoercer.coerce("foo", Collection.class);
>       System.out.println("RESULT: " + result);
>       if (!expected.equals(result)) {
>         throw new Exception(expected + " != " + result);
>       }
>     } finally {
>       registry.shutdown();
>     }
>   }
> }
> {code}
> Stacktrace:
> {code:java}
> Exception in thread "main" java.lang.RuntimeException: Coercion of foo to 
> type java.util.Collection (via String --> 
> org.apache.tapestry5.json.JSONArray) failed: A JSONArray text must start with 
> '[' (actual: 'f') at character 1 of foo
>     at 
> org.apache.tapestry5.commons.internal.services.TypeCoercerImpl$TargetCoercion.coerce(TypeCoercerImpl.java:79)
>     at 
> org.apache.tapestry5.commons.internal.services.TypeCoercerImpl.coerce(TypeCoercerImpl.java:155)
>     at $TypeCoercer_14735c6695ab1.coerce(Unknown Source)
>     at TypeCoercerBug.main(TypeCoercerBug.java:16)
> Caused by: org.apache.tapestry5.json.exceptions.JSONSyntaxException: A 
> JSONArray text must start with '[' (actual: 'f') at character 1 of foo
>     at org.apache.tapestry5.json.JSONTokener.syntaxError(JSONTokener.java:509)
>     at org.apache.tapestry5.json.JSONTokener.nextValue(JSONTokener.java:119)
>     at org.apache.tapestry5.json.JSONArray.<init>(JSONArray.java:78)
>     at org.apache.tapestry5.json.JSONArray.<init>(JSONArray.java:95)
>     at 
> org.apache.tapestry5.internal.json.StringToJSONArray.coerce(StringToJSONArray.java:26)
>     at 
> org.apache.tapestry5.internal.json.StringToJSONArray.coerce(StringToJSONArray.java:23)
>     at 
> org.apache.tapestry5.commons.services.CoercionTuple$CoercionWrapper.coerce(CoercionTuple.java:57)
>     at 
> org.apache.tapestry5.commons.internal.services.TypeCoercerImpl$TargetCoercion.coerce(TypeCoercerImpl.java:76)
>     ... 3 more
> {code}



--
This message was sent by Atlassian Jira
(v8.3.4#803005)

Reply via email to