Johnzon 1.0.1 change in behaviour for final objects

classic Classic list List threaded Threaded
4 messages Options
Reply | Threaded
Open this post in threaded view
|

Johnzon 1.0.1 change in behaviour for final objects

dave
Hi,

I am attempting to upgrade from TomEE 7.0.4 (Johnzon 1.0.0) to TomEE 7.1.0
(Johnzon 1.0.1) and have encountered a change in behaviour with JSON
deserialization. The below test passes with Johnzon 1.0.0 but fails with
1.0.1.

Tracing this through with the different Johnzon versions it appears the
cause is FieldAccessMode.field() method excluding final fields in 1.0.1.
Johnzon no longer regards the map field "m" as writeable so silently skips
attempting to put its contents. Removing the final modifier from the map
avoids the issue.

Is this behaviour considered erroneous?

Thanks,
Dave

public class JohnzonMapperTest
{
  @Test
  public void testFinalMap()
      throws Exception
  {
    WithFinalMap o = new
MapperBuilder().build().readObject("{\"m\":{\"A\":\"a\"}}", WithMap.class);
    assertEquals("a", o.m.get("A"));
  }


  public static class WithFinalMap
  {
    public final Map<String, Object> m = new HashMap<>();
  }
}




--
Sent from: http://tomee-openejb.979440.n4.nabble.com/TomEE-Users-f979441.html
Reply | Threaded
Open this post in threaded view
|

Re: Johnzon 1.0.1 change in behaviour for final objects

Romain Manni-Bucau
Hi Dave,

yes this is tracked in https://issues.apache.org/jira/browse/JOHNZON-142
and 77

long story short setting final fields was not intended and lead to
inconsistencies so this behavior has been dropped.

if you need the previous behavior and are sure it is intended you can get
it back using:

WithFinalMap o = new MapperBuilder()
        .setAccessMode(new FieldAccessMode(true, true) {
            @Override
            protected Map<String, Field> fields(Class<?> clazz,
boolean includeFinalFields) {
                return super.fields(clazz, true);
            }
        })
        .build().readObject("{\"m\":{\"A\":\"a\"}}", WithFinalMap.class);


That said i wouldnt recommand you to do it and maybe use the constructor
rather than this old hack

Romain Manni-Bucau
@rmannibucau <https://twitter.com/rmannibucau> |  Blog
<https://rmannibucau.metawerx.net/> | Old Blog
<http://rmannibucau.wordpress.com> | Github <https://github.com/rmannibucau> |
LinkedIn <https://www.linkedin.com/in/rmannibucau> | Book
<https://www.packtpub.com/application-development/java-ee-8-high-performance>


Le lun. 29 oct. 2018 à 00:10, dave <[hidden email]> a écrit :

> Hi,
>
> I am attempting to upgrade from TomEE 7.0.4 (Johnzon 1.0.0) to TomEE 7.1.0
> (Johnzon 1.0.1) and have encountered a change in behaviour with JSON
> deserialization. The below test passes with Johnzon 1.0.0 but fails with
> 1.0.1.
>
> Tracing this through with the different Johnzon versions it appears the
> cause is FieldAccessMode.field() method excluding final fields in 1.0.1.
> Johnzon no longer regards the map field "m" as writeable so silently skips
> attempting to put its contents. Removing the final modifier from the map
> avoids the issue.
>
> Is this behaviour considered erroneous?
>
> Thanks,
> Dave
>
> public class JohnzonMapperTest
> {
>   @Test
>   public void testFinalMap()
>       throws Exception
>   {
>     WithFinalMap o = new
> MapperBuilder().build().readObject("{\"m\":{\"A\":\"a\"}}", WithMap.class);
>     assertEquals("a", o.m.get("A"));
>   }
>
>
>   public static class WithFinalMap
>   {
>     public final Map<String, Object> m = new HashMap<>();
>   }
> }
>
>
>
>
> --
> Sent from:
> http://tomee-openejb.979440.n4.nabble.com/TomEE-Users-f979441.html
>
Reply | Threaded
Open this post in threaded view
|

Re: Johnzon 1.0.1 change in behaviour for final objects

dave
Thanks for the explanation Romain.

In this case I have been able to remove the final modifiers from the
affected fields. This was the simplest thing to do as the mapping was being
done automatically in REST API calls rather than explicitly via Johnzon.

The problem did take some tracking down. I can understand the Map field m
not being settable if final, but this also has the effect of causing Johnzon
to silently not set the values within the map even if the map has been
initialised. I presume the same would apply for any nested final objects
containing settable non-final fields. From my perspective it would be
preferable to either support this, or fail fast with an error in such cases.

Regards,
Dave


Romain Manni-Bucau wrote

> Hi Dave,
>
> yes this is tracked in https://issues.apache.org/jira/browse/JOHNZON-142
> and 77
>
> long story short setting final fields was not intended and lead to
> inconsistencies so this behavior has been dropped.
>
> if you need the previous behavior and are sure it is intended you can get
> it back using:
>
> WithFinalMap o = new MapperBuilder()
>         .setAccessMode(new FieldAccessMode(true, true) {
>             @Override
>             protected Map&lt;String, Field&gt; fields(Class<?> clazz,
> boolean includeFinalFields) {
>                 return super.fields(clazz, true);
>             }
>         })
>         .build().readObject("{\"m\":{\"A\":\"a\"}}", WithFinalMap.class);
>
>
> That said i wouldnt recommand you to do it and maybe use the constructor
> rather than this old hack
>
> Romain Manni-Bucau
> @rmannibucau &lt;https://twitter.com/rmannibucau&gt; |  Blog
> &lt;https://rmannibucau.metawerx.net/&gt; | Old Blog
> &lt;http://rmannibucau.wordpress.com&gt; | Github
> &lt;https://github.com/rmannibucau&gt; |
> LinkedIn &lt;https://www.linkedin.com/in/rmannibucau&gt; | Book
> &lt;https://www.packtpub.com/application-development/java-ee-8-high-performance&gt;
>
>
> Le lun. 29 oct. 2018 à 00:10, dave &lt;

> d.eaves@.co

> &gt; a écrit :
>
>> Hi,
>>
>> I am attempting to upgrade from TomEE 7.0.4 (Johnzon 1.0.0) to TomEE
>> 7.1.0
>> (Johnzon 1.0.1) and have encountered a change in behaviour with JSON
>> deserialization. The below test passes with Johnzon 1.0.0 but fails with
>> 1.0.1.
>>
>> Tracing this through with the different Johnzon versions it appears the
>> cause is FieldAccessMode.field() method excluding final fields in 1.0.1.
>> Johnzon no longer regards the map field "m" as writeable so silently
>> skips
>> attempting to put its contents. Removing the final modifier from the map
>> avoids the issue.
>>
>> Is this behaviour considered erroneous?
>>
>> Thanks,
>> Dave
>>
>> public class JohnzonMapperTest
>> {
>>   @Test
>>   public void testFinalMap()
>>       throws Exception
>>   {
>>     WithFinalMap o = new
>> MapperBuilder().build().readObject("{\"m\":{\"A\":\"a\"}}",
>> WithMap.class);
>>     assertEquals("a", o.m.get("A"));
>>   }
>>
>>
>>   public static class WithFinalMap
>>   {
>>     public final Map&lt;String, Object&gt; m = new HashMap<>();
>>   }
>> }
>>
>>
>>
>>
>> --
>> Sent from:
>> http://tomee-openejb.979440.n4.nabble.com/TomEE-Users-f979441.html
>>





--
Sent from: http://tomee-openejb.979440.n4.nabble.com/TomEE-Users-f979441.html
Reply | Threaded
Open this post in threaded view
|

Re: Johnzon 1.0.1 change in behaviour for final objects

Romain Manni-Bucau
Failling fast is not really an option since it is the correct behavior and
does not violate java contract.

We can tune some config like the extsing readAttributeBeforeWrite to reuse
it to read your map and enrich it instead of overwriting it but it can also
lead to inconsistent values when reusing mapped objects.
Getting the map then clearing it before setting it is an option but not
sure it does worth it since the fix is very easy (a setter, dropping final,
@JohnzonAny in an object etc).

Le mar. 30 oct. 2018 04:40, dave <[hidden email]> a écrit :

> Thanks for the explanation Romain.
>
> In this case I have been able to remove the final modifiers from the
> affected fields. This was the simplest thing to do as the mapping was being
> done automatically in REST API calls rather than explicitly via Johnzon.
>
> The problem did take some tracking down. I can understand the Map field m
> not being settable if final, but this also has the effect of causing
> Johnzon
> to silently not set the values within the map even if the map has been
> initialised. I presume the same would apply for any nested final objects
> containing settable non-final fields. From my perspective it would be
> preferable to either support this, or fail fast with an error in such
> cases.
>
> Regards,
> Dave
>
>
> Romain Manni-Bucau wrote
> > Hi Dave,
> >
> > yes this is tracked in https://issues.apache.org/jira/browse/JOHNZON-142
> > and 77
> >
> > long story short setting final fields was not intended and lead to
> > inconsistencies so this behavior has been dropped.
> >
> > if you need the previous behavior and are sure it is intended you can get
> > it back using:
> >
> > WithFinalMap o = new MapperBuilder()
> >         .setAccessMode(new FieldAccessMode(true, true) {
> >             @Override
> >             protected Map&lt;String, Field&gt; fields(Class<?> clazz,
> > boolean includeFinalFields) {
> >                 return super.fields(clazz, true);
> >             }
> >         })
> >         .build().readObject("{\"m\":{\"A\":\"a\"}}", WithFinalMap.class);
> >
> >
> > That said i wouldnt recommand you to do it and maybe use the constructor
> > rather than this old hack
> >
> > Romain Manni-Bucau
> > @rmannibucau &lt;https://twitter.com/rmannibucau&gt; |  Blog
> > &lt;https://rmannibucau.metawerx.net/&gt; | Old Blog
> > &lt;http://rmannibucau.wordpress.com&gt; | Github
> > &lt;https://github.com/rmannibucau&gt; |
> > LinkedIn &lt;https://www.linkedin.com/in/rmannibucau&gt; | Book
> > &lt;
> https://www.packtpub.com/application-development/java-ee-8-high-performance&gt
> ;
> >
> >
> > Le lun. 29 oct. 2018 à 00:10, dave &lt;
>
> > d.eaves@.co
>
> > &gt; a écrit :
> >
> >> Hi,
> >>
> >> I am attempting to upgrade from TomEE 7.0.4 (Johnzon 1.0.0) to TomEE
> >> 7.1.0
> >> (Johnzon 1.0.1) and have encountered a change in behaviour with JSON
> >> deserialization. The below test passes with Johnzon 1.0.0 but fails with
> >> 1.0.1.
> >>
> >> Tracing this through with the different Johnzon versions it appears the
> >> cause is FieldAccessMode.field() method excluding final fields in 1.0.1.
> >> Johnzon no longer regards the map field "m" as writeable so silently
> >> skips
> >> attempting to put its contents. Removing the final modifier from the map
> >> avoids the issue.
> >>
> >> Is this behaviour considered erroneous?
> >>
> >> Thanks,
> >> Dave
> >>
> >> public class JohnzonMapperTest
> >> {
> >>   @Test
> >>   public void testFinalMap()
> >>       throws Exception
> >>   {
> >>     WithFinalMap o = new
> >> MapperBuilder().build().readObject("{\"m\":{\"A\":\"a\"}}",
> >> WithMap.class);
> >>     assertEquals("a", o.m.get("A"));
> >>   }
> >>
> >>
> >>   public static class WithFinalMap
> >>   {
> >>     public final Map&lt;String, Object&gt; m = new HashMap<>();
> >>   }
> >> }
> >>
> >>
> >>
> >>
> >> --
> >> Sent from:
> >> http://tomee-openejb.979440.n4.nabble.com/TomEE-Users-f979441.html
> >>
>
>
>
>
>
> --
> Sent from:
> http://tomee-openejb.979440.n4.nabble.com/TomEE-Users-f979441.html
>