basic unmarshall question

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

basic unmarshall question

js
hi,

I'll eventually figure this out, but i have been struggling for at least 2 days trying to unmarshall the simplest xml.. i must really be getting frustrated if i resorted to emailing the open source developers.. anyway:

all i want to do is unmarshall a simple xml file involving nested collections 

<persons>
        <person><name>billy</name>
                <address>
                        <address1>West St.</address1>
                </address>
                <address>
                        <address1>East St.<address1>
                </address>
        </person>
        <person><name>bob</name>
                <address>
                        <address1>North St.</address1>
                </address>
                <address>
                        <address1>South St.<address1>
                 </address>
        </person>
</persons>


i have tried all the examples at codehaus (which are all marshall-centric)
i have googled countless sites. 
no where have i found a simple, complete example that does this most basic of requirements. 

if collections are created, they are either null or empty.
Lots of: No field "person" for implicit collection errors as well.

====== CODE =========

public class Persons {

    private List<Person> persons = new ArrayList<Person>();

    public List<Person> getPersons() {
        return persons;
    }
    public void setPersons(List<Person> persons) {
        this.persons = persons;
    }

}
//this is a "command" class as one does not need a model class for "persons" thus the List instead of Set (i was just following examples i found online, but would rather it be a set as well).
//also, why examples have get() and add(), instead of POJO get(), set()?

---------

public class Person {

    private String name;
    private Set<Address> addresses = new HashSet<Address>();

    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }


    public Set<Address> getAddresses() {
        return addresses;
    }
    public void setAddresses(Set<Address> addresses) {
        this.addresses = addresses;
    }
}

//are complete constructors required?

-------------

public class Address {

    private String address1;

    public String getAddress1() {
        return address1;
    }
    public void setAddress1(String address1) {
        this.address1 = address1;
    }

}

--------------

public void personsFromXML(MultipartFile xml) {        
        XStream xstream = new XStream(new StaxDriver());
        Persons persons = new Persons();
        xstream.alias("persons", Persons.class);
        
        try {
            persons = (Persons)xstream.fromXML(xml.getInputStream());            
        }
        catch(Exception e){
            e.printStackTrace();
        }

--------------

i have tried annotations in Persons.class as well as all variations of the below (+ others):
//xstream.addImplicitCollection(Person.class, "person");     
        //xstream.alias("persons", Persons.class);
        //xstream.alias("person", Person.class);
       //xstream.alias("address", Address.class);
        //xstream.addImplicitCollection(Person.class, "person");
        //xstream.addImplicitCollection(Person.class, "person", Persons.class);
        //xstream.addImplicitCollection(Persons.class, "person", Person.class);

how does xstream know that collection A is within Persons.class, but collection B is in Person.class?

are the generic converters being used when xtream performs its auto-deserialization magic? 

are aliases and implicitCollections handled diff when marshall v. unmarshall?


thx for the read,
-J

Reply | Threaded
Open this post in threaded view
|

Re: basic unmarshall question

Jörg Schaible-4
Hi John,

js wrote:

> hi,
>
> I'll eventually figure this out, but i have been struggling for at least 2
> days trying to unmarshall the simplest xml.. i must really be getting
> frustrated if i resorted to emailing the open source developers.. anyway:
>
> all i want to do is unmarshall a simple xml file involving nested
> collections
>
> <persons>
>         <person><name>billy</name>
>                 <address>
>                         <address1>West St.</address1>
>                 </address>
>                 <address>
>                         <address1>East St.<address1>
>                 </address>
>         </person>
>         <person><name>bob</name>
>                 <address>
>                         <address1>North St.</address1>
>                 </address>
>                 <address>
>                         <address1>South St.<address1>
>                  </address>
>         </person>
> </persons>
>
>
> i have tried all the examples at codehaus (which are all
> marshall-centric).


Well, no. Not really. See, XStream is about Java object to XML *and back*,
i.e. every example can also unmarshal.


> i have googled countless sites.
> no where have i found a simple, complete example that does this most basic
> of requirements.


Because it's not necessary? ... see below ;-)

 

> if collections are created, they are either null or empty.
> Lots of: No field "person" for implicit collection errors as well.
>
> ====== CODE =========
>
> public class Persons {
>
>     private List<Person> persons = new ArrayList<Person>();
>
>     public List<Person> getPersons() {
>         return persons;
>     }
>     public void setPersons(List<Person> persons) {
>         this.persons = persons;
>     }
>
> }
> //this is a "command" class as one does not need a model class for
> "persons" thus the List instead of Set (i was just following examples i
> found online, but would rather it be a set as well).


You may also use directly an array (Person[]).


> //also, why examples have get() and add(), instead of POJO get(), set()?


Why do you think the objects have to be POJOs?

 

> ---------
>
> public class Person {
>
>     private String name;
>     private Set<Address> addresses = new HashSet<Address>();
>
>     public String getName() {
>         return name;
>     }
>     public void setName(String name) {
>         this.name = name;
>     }
>
>
>     public Set<Address> getAddresses() {
>         return addresses;
>     }
>     public void setAddresses(Set<Address> addresses) {
>         this.addresses = addresses;
>     }
> }
>
> //are complete constructors required?


Neither constructors nor setters are required.

> -------------
>
> public class Address {
>
>     private String address1;
>
>     public String getAddress1() {
>         return address1;
>     }
>     public void setAddress1(String address1) {
>         this.address1 = address1;
>     }
>
> }
>
> --------------
>
> public void personsFromXML(MultipartFile xml) {
>         XStream xstream = new XStream(new StaxDriver());
>         Persons persons = new Persons();
>         xstream.alias("persons", Persons.class);
>
>         try {
>             persons = (Persons)xstream.fromXML(xml.getInputStream());
>
>         }
>         catch(Exception e){
>             e.printStackTrace();
>         }
>
> --------------
>
> i have tried annotations in Persons.class as well as all variations of the
> below (+ others):
> //xstream.addImplicitCollection(Person.class, "person");
>         //xstream.alias("persons", Persons.class);
>         //xstream.alias("person", Person.class);
>        //xstream.alias("address", Address.class);
>         //xstream.addImplicitCollection(Person.class, "person");
>         //xstream.addImplicitCollection(Person.class, "person",
> Persons.class);
>         //xstream.addImplicitCollection(Persons.class, "person",
> Person.class);


http://xstream.codehaus.org/faq.html#XML_unmarshalling_fails

Therefore adjust the marshalling. If XStream generates the required XML
format, it can also read it. It is a very tedious and annoying task to try
it the other way round (you already found this out), because you never know
- especially as starter - why XStream throws an exception or silently skips
some elements.

 
> how does xstream know that collection A is within Persons.class, but
> collection B is in Person.class?


Java reflection.


> are the generic converters being used when xtream performs its
> auto-deserialization magic?


Since XStream has obviously no built-in converters for Person or Address, it
has to use the generic converters (based on reflection).


> are aliases and implicitCollections handled diff when marshall v.
> unmarshall?


No. That's the point. Adjust the XStream and write an object as XML and you
will see immediately what has been influenced.

Hope this helps,
Jörg


---------------------------------------------------------------------
To unsubscribe from this list, please visit:

    http://xircles.codehaus.org/manage_email


js
Reply | Threaded
Open this post in threaded view
|

Re: basic unmarshall question

js
<Jörg>
Well, no. Not really. See, XStream is about Java object to XML *and back*,
i.e. every example can also unmarshal.

Therefore adjust the marshalling. If XStream generates the required XML
format, it can also read it. It is a very tedious and annoying task to try
it the other way round (you already found this out), because you never know
- especially as starter - why XStream throws an exception or silently skips
some elements.
</Jörg>

<me>
Typically, the use cases will be objects->xml for use by 3rd party or xml->objects where inbound xml was created by a 3rd party. Unless i was simply persisting and reading unmodified serialized data, i would expect that the inbound and outbound xml is different and created/digested by applications that may not even be java.

i created (marshalled/serialized) some test xml as follows:
Persons ps = new Persons();
Person p1 = new Person();
p1.setName("joe");
 s.getPersons().add(p1);
Person p2 = new Person();
p1.setName("blo");
ps.getPersons().add(p2);
System.out.println(xstream.toXML(ps));

while i *try* to unmarshalled/deserialize as follows:
XStream xstream = new XStream(new StaxDriver());
stream.alias("persons", Persons.class);
xstream.alias("person", Person.class);
xstream.addImplicitCollection(Person.class, "person");
etc.

These seems to be a very different set of methods. My problem is that i can't find adequate examples (or documentation) on how to use alias() and addImplicitCollection() methods when unmarshalling collections. 
</me>

---

<Jörg>
Why do you think the objects have to be POJOs?
</Jörg>

<me>
My xml needs to get deserialized into objects and then those objects used by the application. Why not unmarshall directly into my existing POJOs instead of having to create a whole new set of "command" (abstraction) classes whose only difference is that their accessors/mutators are get(), add() instead of the POJO standard get(), set()?
Things are much cleaner if i can (un)marshall using a simple library and leave my domain unmodified (which is why i'm trying to avoid xstream annotations).
I questioned the requirement of get(), add() and collections as lists, because that is whats used in the examples and i thought maybe they were required.
</me>


On Tue, May 20, 2014 at 6:22 AM, Jörg Schaible <[hidden email]> wrote:
Hi John,

js wrote:

> hi,
>
> I'll eventually figure this out, but i have been struggling for at least 2
> days trying to unmarshall the simplest xml.. i must really be getting
> frustrated if i resorted to emailing the open source developers.. anyway:
>
> all i want to do is unmarshall a simple xml file involving nested
> collections
>
> <persons>
>         <person><name>billy</name>
>                 <address>
>                         <address1>West St.</address1>
>                 </address>
>                 <address>
>                         <address1>East St.<address1>
>                 </address>
>         </person>
>         <person><name>bob</name>
>                 <address>
>                         <address1>North St.</address1>
>                 </address>
>                 <address>
>                         <address1>South St.<address1>
>                  </address>
>         </person>
> </persons>
>
>
> i have tried all the examples at codehaus (which are all
> marshall-centric).


Well, no. Not really. See, XStream is about Java object to XML *and back*,
i.e. every example can also unmarshal.


> i have googled countless sites.
> no where have i found a simple, complete example that does this most basic
> of requirements.


Because it's not necessary? ... see below ;-)


> if collections are created, they are either null or empty.
> Lots of: No field "person" for implicit collection errors as well.
>
> ====== CODE =========
>
> public class Persons {
>
>     private List<Person> persons = new ArrayList<Person>();
>
>     public List<Person> getPersons() {
>         return persons;
>     }
>     public void setPersons(List<Person> persons) {
>         this.persons = persons;
>     }
>
> }
> //this is a "command" class as one does not need a model class for
> "persons" thus the List instead of Set (i was just following examples i
> found online, but would rather it be a set as well).


You may also use directly an array (Person[]).


> //also, why examples have get() and add(), instead of POJO get(), set()?


Why do you think the objects have to be POJOs?


> ---------
>
> public class Person {
>
>     private String name;
>     private Set<Address> addresses = new HashSet<Address>();
>
>     public String getName() {
>         return name;
>     }
>     public void setName(String name) {
>         this.name = name;
>     }
>
>
>     public Set<Address> getAddresses() {
>         return addresses;
>     }
>     public void setAddresses(Set<Address> addresses) {
>         this.addresses = addresses;
>     }
> }
>
> //are complete constructors required?


Neither constructors nor setters are required.

> -------------
>
> public class Address {
>
>     private String address1;
>
>     public String getAddress1() {
>         return address1;
>     }
>     public void setAddress1(String address1) {
>         this.address1 = address1;
>     }
>
> }
>
> --------------
>
> public void personsFromXML(MultipartFile xml) {
>         XStream xstream = new XStream(new StaxDriver());
>         Persons persons = new Persons();
>         xstream.alias("persons", Persons.class);
>
>         try {
>             persons = (Persons)xstream.fromXML(xml.getInputStream());
>
>         }
>         catch(Exception e){
>             e.printStackTrace();
>         }
>
> --------------
>
> i have tried annotations in Persons.class as well as all variations of the
> below (+ others):
> //xstream.addImplicitCollection(Person.class, "person");
>         //xstream.alias("persons", Persons.class);
>         //xstream.alias("person", Person.class);
>        //xstream.alias("address", Address.class);
>         //xstream.addImplicitCollection(Person.class, "person");
>         //xstream.addImplicitCollection(Person.class, "person",
> Persons.class);
>         //xstream.addImplicitCollection(Persons.class, "person",
> Person.class);


http://xstream.codehaus.org/faq.html#XML_unmarshalling_fails

Therefore adjust the marshalling. If XStream generates the required XML
format, it can also read it. It is a very tedious and annoying task to try
it the other way round (you already found this out), because you never know
- especially as starter - why XStream throws an exception or silently skips
some elements.


> how does xstream know that collection A is within Persons.class, but
> collection B is in Person.class?


Java reflection.


> are the generic converters being used when xtream performs its
> auto-deserialization magic?


Since XStream has obviously no built-in converters for Person or Address, it
has to use the generic converters (based on reflection).


> are aliases and implicitCollections handled diff when marshall v.
> unmarshall?


No. That's the point. Adjust the XStream and write an object as XML and you
will see immediately what has been influenced.

Hope this helps,
Jörg


---------------------------------------------------------------------
To unsubscribe from this list, please visit:

    http://xircles.codehaus.org/manage_email



Reply | Threaded
Open this post in threaded view
|

Re: Re: basic unmarshall question

Jörg Schaible-2
Hi John,

js wrote:

> <Jörg>
> Well, no. Not really. See, XStream is about Java object to XML *and back*,
> i.e. every example can also unmarshal.
>
> Therefore adjust the marshalling. If XStream generates the required XML
> format, it can also read it. It is a very tedious and annoying task to try
> it the other way round (you already found this out), because you never
> know - especially as starter - why XStream throws an exception or silently
> skips some elements.
> </Jörg>
>
> <me>
> Typically, the use cases will be objects->xml for use by 3rd party or
> xml->objects where inbound xml was created by a 3rd party. Unless i was
> simply persisting and reading unmodified serialized data, i would expect
> that the inbound and outbound xml is different and created/digested by
> applications that may not even be java.


Your expectation does not have any influence, how XStream works.


> i created (marshalled/serialized) some test xml as follows:
> Persons ps = new Persons();
> Person p1 = new Person();
> p1.setName("joe");
>  s.getPersons().add(p1);
> Person p2 = new Person();
> p1.setName("blo");
> ps.getPersons().add(p2);
> System.out.println(xstream.toXML(ps));
>

> while i *try* to unmarshalled/deserialize as follows:
> XStream xstream = new XStream(new StaxDriver());
> stream.alias("persons", Persons.class);
> xstream.alias("person", Person.class);
> xstream.addImplicitCollection(Person.class, "person");
> etc.
>
> These seems to be a very different set of methods.


??

Sorry, but I don't understand your comment. With those methods you influence
the XML format that is written *and* read.

================ %< ===================
Persons ps = new Persons();
Person p1 = new Person();
p1.setName("joe");
s.getPersons().add(p1);
Person p2 = new Person();
p1.setName("blo");
ps.getPersons().add(p2);

XStream xstream = new XStream(new StaxDriver());
xstream.alias("persons", Persons.class);
xstream.alias("person", Person.class);
// next is useless, Person.class has no member person
xstream.addImplicitCollection(Person.class, "person");

String xml = xstream.toXML(ps);
System.out.println(xml);
assertEquals(ps, xtream.fromXML(xml));
================ %< ===================

Will work (proper equals() implementations implied). It simply does not yet
write XML in the format you'd like to read in the end.

> My problem is that i
> can't find adequate examples (or documentation) on how to use alias() and
> addImplicitCollection() methods when unmarshalling collections.

Again, there's no difference between marshalling and unmarshalling. The
question is, which part of the tutorial do you not understand?

http://xstream.codehaus.org/alias-tutorial.html

- Jörg

> </me>
>
> ---
>
> <Jörg>
> Why do you think the objects have to be POJOs?
> </Jörg>
>
> <me>
> My xml needs to get deserialized into objects and then those objects used
> by the application. Why not unmarshall directly into my existing POJOs
> instead of having to create a whole new set of "command" (abstraction)
> classes whose only difference is that their accessors/mutators are get(),
> add() instead of the POJO standard get(), set()?


XStream does not call any of the methods.


> Things are much cleaner if i can (un)marshall using a simple library and
> leave my domain unmodified (which is why i'm trying to avoid xstream
> annotations).


Personally, I don't use annotations either - for exactly the same reason.
However, why do you think you cannot read/write into your domain model?
That's what I normally do with XStream. Procedure is the same again: Write
your domain model objects as XML and then start to tweak the output.


> I questioned the requirement of get(), add() and collections as lists,
> because that is whats used in the examples and i thought maybe they were
> required.


The generic (reflection-based) converters will look for declared members
only. No methods or constructors required.

Cheers,
Jörg


---------------------------------------------------------------------
To unsubscribe from this list, please visit:

    http://xircles.codehaus.org/manage_email


js
Reply | Threaded
Open this post in threaded view
|

Re: Re: basic unmarshall question

js
Jörg, got it.. it works..thank you
i guess i was just looking for that "aha" moment... which your feedback provided.

in the alias tutorial, even though it says "..make XStream read/write", it never really set in that it was anything other than a marshall example.
An actual unmarshall method there (and in the other examples) would drive home your point that alias() and addImplicitCollection() is applicable to both serialize and deserialize.

your advice to first create the xml via xstream methods makes perfect sense now.
i was able to find duplicate <persons> elements (class name and collection name) and move forward quickly without the previous errors.

again, thanks






On Tue, May 20, 2014 at 10:17 AM, Jörg Schaible <[hidden email]> wrote:
Hi John,

js wrote:

> <Jörg>
> Well, no. Not really. See, XStream is about Java object to XML *and back*,
> i.e. every example can also unmarshal.
>
> Therefore adjust the marshalling. If XStream generates the required XML
> format, it can also read it. It is a very tedious and annoying task to try
> it the other way round (you already found this out), because you never
> know - especially as starter - why XStream throws an exception or silently
> skips some elements.
> </Jörg>
>
> <me>
> Typically, the use cases will be objects->xml for use by 3rd party or
> xml->objects where inbound xml was created by a 3rd party. Unless i was
> simply persisting and reading unmodified serialized data, i would expect
> that the inbound and outbound xml is different and created/digested by
> applications that may not even be java.


Your expectation does not have any influence, how XStream works.


> i created (marshalled/serialized) some test xml as follows:
> Persons ps = new Persons();
> Person p1 = new Person();
> p1.setName("joe");
>  s.getPersons().add(p1);
> Person p2 = new Person();
> p1.setName("blo");
> ps.getPersons().add(p2);
> System.out.println(xstream.toXML(ps));
>

> while i *try* to unmarshalled/deserialize as follows:
> XStream xstream = new XStream(new StaxDriver());
> stream.alias("persons", Persons.class);
> xstream.alias("person", Person.class);
> xstream.addImplicitCollection(Person.class, "person");
> etc.
>
> These seems to be a very different set of methods.


??

Sorry, but I don't understand your comment. With those methods you influence
the XML format that is written *and* read.

================ %< ===================
Persons ps = new Persons();
Person p1 = new Person();
p1.setName("joe");
s.getPersons().add(p1);
Person p2 = new Person();
p1.setName("blo");
ps.getPersons().add(p2);

XStream xstream = new XStream(new StaxDriver());
xstream.alias("persons", Persons.class);
xstream.alias("person", Person.class);
// next is useless, Person.class has no member person
xstream.addImplicitCollection(Person.class, "person");

String xml = xstream.toXML(ps);
System.out.println(xml);
assertEquals(ps, xtream.fromXML(xml));
================ %< ===================

Will work (proper equals() implementations implied). It simply does not yet
write XML in the format you'd like to read in the end.

> My problem is that i
> can't find adequate examples (or documentation) on how to use alias() and
> addImplicitCollection() methods when unmarshalling collections.

Again, there's no difference between marshalling and unmarshalling. The
question is, which part of the tutorial do you not understand?

http://xstream.codehaus.org/alias-tutorial.html

- Jörg

> </me>
>
> ---
>
> <Jörg>
> Why do you think the objects have to be POJOs?
> </Jörg>
>
> <me>
> My xml needs to get deserialized into objects and then those objects used
> by the application. Why not unmarshall directly into my existing POJOs
> instead of having to create a whole new set of "command" (abstraction)
> classes whose only difference is that their accessors/mutators are get(),
> add() instead of the POJO standard get(), set()?


XStream does not call any of the methods.


> Things are much cleaner if i can (un)marshall using a simple library and
> leave my domain unmodified (which is why i'm trying to avoid xstream
> annotations).


Personally, I don't use annotations either - for exactly the same reason.
However, why do you think you cannot read/write into your domain model?
That's what I normally do with XStream. Procedure is the same again: Write
your domain model objects as XML and then start to tweak the output.


> I questioned the requirement of get(), add() and collections as lists,
> because that is whats used in the examples and i thought maybe they were
> required.


The generic (reflection-based) converters will look for declared members
only. No methods or constructors required.

Cheers,
Jörg


---------------------------------------------------------------------
To unsubscribe from this list, please visit:

    http://xircles.codehaus.org/manage_email



Reply | Threaded
Open this post in threaded view
|

Re: Re: Re: basic unmarshall question

Jörg Schaible-4
Hi John,

js wrote:

> Jörg, got it.. it works..thank you
> i guess i was just looking for that "aha" moment... which your feedback
> provided.


Glad to here.

 
> in the alias tutorial, even though it says "..make XStream read/write", it
> never really set in that it was anything other than a marshall example.
> An actual unmarshall method there (and in the other examples) would drive
> home your point that alias() and addImplicitCollection() is applicable to
> both serialize and deserialize.


For us developers it's natural that it works in both directions. Maybe this
is our blind spot here. I'll try to improve the docs for the next release.


> your advice to first create the xml via xstream methods makes perfect
> sense now.
> i was able to find duplicate <persons> elements (class name and collection
> name) and move forward quickly without the previous errors.


Development is efficient and much less frustrating that way. I know.

 
> again, thanks


You're welcome,
Jörg



---------------------------------------------------------------------
To unsubscribe from this list, please visit:

    http://xircles.codehaus.org/manage_email