Return-Path: X-Original-To: archive-asf-public-internal@cust-asf2.ponee.io Delivered-To: archive-asf-public-internal@cust-asf2.ponee.io Received: from cust-asf.ponee.io (cust-asf.ponee.io [163.172.22.183]) by cust-asf2.ponee.io (Postfix) with ESMTP id 60021200B75 for ; Sun, 21 Aug 2016 07:46:39 +0200 (CEST) Received: by cust-asf.ponee.io (Postfix) id 5E913160ABE; Sun, 21 Aug 2016 05:46:39 +0000 (UTC) Delivered-To: archive-asf-public@cust-asf.ponee.io Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by cust-asf.ponee.io (Postfix) with SMTP id 7E826160ABB for ; Sun, 21 Aug 2016 07:46:38 +0200 (CEST) Received: (qmail 85928 invoked by uid 500); 21 Aug 2016 05:46:37 -0000 Mailing-List: contact dev-help@felix.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@felix.apache.org Delivered-To: mailing list dev@felix.apache.org Received: (qmail 85913 invoked by uid 99); 21 Aug 2016 05:46:37 -0000 Received: from pnap-us-west-generic-nat.apache.org (HELO spamd2-us-west.apache.org) (209.188.14.142) by apache.org (qpsmtpd/0.29) with ESMTP; Sun, 21 Aug 2016 05:46:37 +0000 Received: from localhost (localhost [127.0.0.1]) by spamd2-us-west.apache.org (ASF Mail Server at spamd2-us-west.apache.org) with ESMTP id C1D3E1A01BD for ; Sun, 21 Aug 2016 05:46:36 +0000 (UTC) X-Virus-Scanned: Debian amavisd-new at spamd2-us-west.apache.org X-Spam-Flag: NO X-Spam-Score: 0.3 X-Spam-Level: X-Spam-Status: No, score=0.3 tagged_above=-999 required=6.31 tests=[KAM_LAZY_DOMAIN_SECURITY=1, RCVD_IN_DNSWL_LOW=-0.7] autolearn=disabled Received: from mx1-lw-eu.apache.org ([10.40.0.8]) by localhost (spamd2-us-west.apache.org [10.40.0.9]) (amavisd-new, port 10024) with ESMTP id hHHe2eXuOVNI for ; Sun, 21 Aug 2016 05:46:34 +0000 (UTC) Received: from mailout.easydns.com (mailout.easydns.com [64.68.201.141]) by mx1-lw-eu.apache.org (ASF Mail Server at mx1-lw-eu.apache.org) with ESMTPS id E08A95F3F2 for ; Sun, 21 Aug 2016 05:46:33 +0000 (UTC) Received: from localhost (localhost [127.0.0.1]) by mailout.easydns.com (Postfix) with ESMTP id B200E12F430 for ; Sun, 21 Aug 2016 01:46:30 -0400 (EDT) X-Virus-Scanned: Debian amavisd-new at mailout.easydns.com Received: from mailout.easydns.com ([127.0.0.1]) by localhost (mailout.easydns.com [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id htaGUhkgHbq0 for ; Sun, 21 Aug 2016 01:46:28 -0400 (EDT) Received: from [172.20.10.2] (KD106129019062.au-net.ne.jp [106.129.19.62]) (using TLSv1 with cipher ECDHE-RSA-AES256-SHA (256/256 bits)) (No client certificate requested) by mailout.easydns.com (Postfix) with ESMTPSA id 169F512F428 for ; Sun, 21 Aug 2016 01:46:27 -0400 (EDT) Content-Type: text/plain; charset=utf-8 Mime-Version: 1.0 (Mac OS X Mail 9.3 \(3124\)) Subject: Re: [Converter] Serializer From: David Leangen In-Reply-To: <056390CA-64B1-4DBA-ADCB-4DE3DF9CA335@gmail.com> Date: Sun, 21 Aug 2016 14:46:19 +0900 Content-Transfer-Encoding: quoted-printable Message-Id: <20402349-BEA0-49AF-AE22-28C7793876F8@leangen.net> References: <940E5AF8-E462-4639-868A-ED7C04E2BF50@leangen.net> <4A2EB6ED-93EF-401A-8379-47C65FA0DD8A@leangen.net> <056390CA-64B1-4DBA-ADCB-4DE3DF9CA335@gmail.com> To: dev@felix.apache.org X-Mailer: Apple Mail (2.3124) archived-at: Sun, 21 Aug 2016 05:46:39 -0000 Hi Johan, Thanks for your thoughts. Are you able to elaborate a little more? > Whenever you serialize and say =E2=80=9CHey=E2=80=99 let=E2=80=99s use = polymorphism", you are pretty=20 > much bound to fail. I=E2=80=99m not sure why you say this. I thought that by including the = schema information, that is exactly what we were avoiding=E2=80=A6 I=E2=80=99m not sure I=E2=80=99m getting your idea about the command = pattern. Would you mind showing me a quick example? Cheers, =3DDavid > On Aug 21, 2016, at 2:42 PM, Johan Edstrom wrote: >=20 > Whenever you serialize and say =E2=80=9CHey=E2=80=99 let=E2=80=99s use = polymorphism", you are pretty=20 > much bound to fail. >=20 > Use something like a command pattern identifying what you are doing=20 > so you can pick the de-serializer.=20 >=20 >=20 >=20 >> On Aug 20, 2016, at 11:32 PM, David Leangen wrote: >>=20 >>=20 >> I had a few thoughts about this topic. >>=20 >> In order to properly deserialise, we would need the schema. Since the = DTO type *is* the schema, then somehow the schema needs to be serialised = as well, or at least known upon serialisation. >>=20 >> If the API were to have a toSchema() method, that would simplify = things a lot. A client should also be able to do something like this: >>=20 >> SomeDTO dto =3D ... >> codec.encode( dto ).serializeTo( out ); >>=20 >> Or maybe: >>=20 >> codec.withSchema( SomeDTO.class).encode( dto ).to( out ); >>=20 >> The SomeDTO schema would also be serialised (perhaps simply using the = fully-qualified class name as an alias?), so then the client could do = this: >>=20 >> Object o =3D codec.deserializeFrom( in ) >>=20 >> Since the schema is included in the input data, the serializer will = behind the scene do something like: >>=20 >>=20 >> Map map =3D codec.decode( Map.class ).from( in ); >> // Get the schema type, which is SomeDTO.class >> ... >> Object o =3D converter.convert( map.get(=E2=80=9Cdata=E2=80=9D) = ).to( SomeDTO.class ); >>=20 >>=20 >> wdyt? >>=20 >> =3DDavid >>=20 >>=20 >>=20 >>> On Aug 20, 2016, at 3:23 PM, David Leangen wrote: >>>=20 >>>=20 >>> Hi, >>>=20 >>> I am trying to use the Convert/Codec as a serializer, but it has = been a bit of a struggle so far. >>>=20 >>> I have a =E2=80=9Cdeep=E2=80=9D object structure (i.e. at least one = level of embedded objects). Writing the data as a JSON string works just = fine. However, when deserialising, I am having trouble. The data object = uses generics, so it is not possible to determine the type at runtime. = My embedded objects end up being deserialised as Maps, which of course = causes a ClassCastException later on in the code. >>>=20 >>> I have tried adding a Rule using an adapter, and setting the = codec.with(thatAdapter), but that didn=E2=80=99t work out so well, = either. >>>=20 >>> Here is an example of my attempt so far. I am working with = Prevayler, so I need to serialize/deserialze a command object, which = contains some data. >>>=20 >>> I think that this code _should_ work, which means that there is = likely a bug in the code. Even so=E2=80=A6 >>>=20 >>> This is a very convoluted way of working, which doesn=E2=80=99t seem = right to me. Am I missing some concept? >>>=20 >>>=20 >>> Example below. >>>=20 >>> Cheers, >>> =3DDavid >>>=20 >>>=20 >>> public class DTOSerializer >>> implements Serializer // This is the interface provided by = Prevayler >>> { >>> private final Converter converter; >>> private final Codec codec; >>> private final Class type; >>>=20 >>> public DTOSerializer( Converter aConverter, Codec aCodec, Class = aType ) >>> { >>> // Very convoluted attempt at adding a rule to try to make the = conversion of my =E2=80=9CPutCommand=E2=80=9D work during = deserialization >>> converter =3D aConverter.getAdapter() >>> .rule(=20 >>> PutCommand.class,=20 >>> Map.class,=20 >>> dto -> { Map map =3D new HashMap<>(); map.put( = "key", dto.key ); map.put( "entity", dto.entity ); return map; },=20 >>> map -> { PutCommand c =3D new PutCommand(); = c.key =3D (String)map.get( "key" ); c.entity =3D aConverter.convert( = map.get( "entity" ) ).to( aType ); return c; } ); >>> codec =3D aCodec.with( converter ); >>> } >>>=20 >>> @Override >>> public Object readObject( InputStream in ) >>> throws Exception >>> { >>> // This is the raw data >>> final Map map =3D codec.decode( Map.class = ).from( in ); >>> // The name of the object type to cast to >>> final String commandTypeName =3D (String)map.get( "command" ); >>> final Class commandType =3D Class.forName( commandTypeName = ); >>> // This indeed returns an object of the correct type, >>> // HOWEVER, the embedded objects are not of the correct type, = they are of type Map >>> final Object command =3D converter.convert( map.get( "payload" = ) ).to( commandType ); >>> return command; >>> } >>>=20 >>> @Override >>> public void writeObject( OutputStream out, Object object ) >>> throws Exception >>> { >>> final Map map =3D new HashMap<>(); >>> // Serialize the name of the command so I know what to cast it = do when deserializing >>> map.put( "command", object.getClass().getName() ); >>> // This is the actual payload, which is nothing more than the = command object >>> map.put( "payload", object ); >>> codec.encode( map ).to( out ); >>> } >>> } >>>=20 >>=20 >=20