@@ -124,6 +124,7 @@ public class EntityEncodingManager {
124124
125125 private static final ObjectMapper JSON_MAPPER = MapperFactory .jsonBuilder ()
126126 .ignoreUnknownProperties ()
127+ .registerJdk8Module ()
127128 .registerJavaTimeModule ()
128129 .disableDateTimestamps ()
129130 .disableFailOnEmptyBeans ()
@@ -474,6 +475,11 @@ public Object internalInputTranslator(EntityReference ref, String format, InputS
474475 */
475476 public void internalOutputFormatter (EntityReference ref , String format , List <EntityData > entities , Map <String , Object > params , OutputStream output , EntityView view ) {
476477 if (format == null ) { format = Outputable .HTML ; }
478+ String originalFormat = format ;
479+ format = format .trim ();
480+ if (!format .equals (originalFormat )) {
481+ log .debug ("Trimmed format '{}' -> '{}' for ref {}" , originalFormat , format , ref );
482+ }
477483
478484 // check the format to see if we can handle it
479485 if (! contains (HANDLED_OUTPUT_FORMATS , format )) {
@@ -608,6 +614,11 @@ public String encodeEntity(String prefix, String format, EntityData entityData,
608614 if (prefix == null || format == null ) {
609615 throw new IllegalArgumentException ("prefix and format must not be null" );
610616 }
617+ String originalFormat = format ;
618+ format = format .trim ();
619+ if (!format .equals (originalFormat )) {
620+ log .debug ("Trimmed encodeEntity format '{}' -> '{}' for prefix {}" , originalFormat , format , prefix );
621+ }
611622 if (entityData == null && ! Formats .FORM .equals (format )) {
612623 throw new IllegalArgumentException ("entityData to encode must not be null for prefix (" +prefix +") and format (" +format +")" );
613624 }
@@ -840,15 +851,31 @@ public String encodeEntity(String prefix, String format, EntityData entityData,
840851 }
841852 }
842853 // do the encoding
854+ String encodingName = prefix ;
855+ if ((beanEncodedDirectly || dataOnly ) && (Formats .JSON .equals (format ) || Formats .JSONP .equals (format ))) {
856+ encodingName = null ;
857+ }
843858 try {
844- String encodingName = prefix ;
845- if ((beanEncodedDirectly || dataOnly ) && (Formats .JSON .equals (format ) || Formats .JSONP .equals (format ))) {
846- encodingName = null ;
847- }
848859 encoded = encodeData (toEncode , format , encodingName , entityProps );
849- } catch (IllegalArgumentException e ) {
850- // no transcoder so just toString this and dump it out
851- encoded = prefix + " : " + entityData ;
860+ } catch (RuntimeException e ) {
861+ log .warn ("encodeEntity fallback for prefix={} format={} dataOnly={} beanEncodedDirectly={} entityClass={}" ,
862+ prefix , format , dataOnly , beanEncodedDirectly , toEncode != null ? toEncode .getClass () : null , e );
863+ if (Formats .JSON .equals (format ) || Formats .JSONP .equals (format )) {
864+ try {
865+ Object envelope = mergeProperties (toEncode , entityProps );
866+ if (encodingName != null && !encodingName .isEmpty ()) {
867+ LinkedHashMap <String , Object > wrapper = new LinkedHashMap <String , Object >();
868+ wrapper .put (encodingName , envelope );
869+ envelope = wrapper ;
870+ }
871+ encoded = JSON_PRETTY_WRITER .writeValueAsString (envelope );
872+ } catch (JsonProcessingException jpe ) {
873+ throw new EntityEncodingException ("Failure encoding data (" + toEncode + ") of type ("
874+ + toEncode .getClass () + ")" , prefix , jpe );
875+ }
876+ } else {
877+ throw e ;
878+ }
852879 }
853880 }
854881 return encoded ;
@@ -983,13 +1010,18 @@ private Object convertValueForSerialization(Object value, int currentDepth, int
9831010 }
9841011 return converted ;
9851012 } else if (isBeanClass (value .getClass ())) {
986- Map <String , Object > beanValues = getObjectValues (value );
987- Map <String , Object > converted = new LinkedHashMap <String , Object >(beanValues .size ());
988- for (Entry <String , Object > entry : beanValues .entrySet ()) {
989- converted .put (entry .getKey (),
990- convertValueForSerialization (entry .getValue (), currentDepth + 1 , maxDepth , visited ));
1013+ try {
1014+ Map <String , Object > beanValues = getObjectValues (value );
1015+ Map <String , Object > converted = new LinkedHashMap <String , Object >(beanValues .size ());
1016+ for (Entry <String , Object > entry : beanValues .entrySet ()) {
1017+ converted .put (entry .getKey (),
1018+ convertValueForSerialization (entry .getValue (), currentDepth + 1 , maxDepth , visited ));
1019+ }
1020+ return converted ;
1021+ } catch (RuntimeException ex ) {
1022+ log .debug ("Bean conversion failed for {}, deferring to serializer: {}" , value .getClass (), ex .toString ());
1023+ return value ; // let Jackson handle it directly
9911024 }
992- return converted ;
9931025 } else {
9941026 return summarizeValue (value );
9951027 }
0 commit comments