XMLEnocder mess.. (Java)

Soldato
Joined
23 Dec 2010
Posts
3,483
Hey guys,

I posted a similar thread earlier on in the month, but there seemed to be some sort of confusion regarding what I was actually asking.

For one of our modules we were asked to create a program which takes some objects and stores them into files using three different methods – Text, XML and Serializable.

I was able to do Serializable and Text, but I seem to be having some confusion with XML.

I have two classes, Books and Authors.

Books are set into the Author using names – so the code looks something akin to this..

Book class -

Instance = private Author who;

Code:
public void setAuthor(ArrayList<Author> authors) {  
         this.who = who;
 }

and in the Author class..
.
Code:
     public void setBooks(ArrayList<Book> books) {
         this.books = books;
     }
 

     public ArrayList<Book> getBooks() {
         return books;
     }

This is what the XML code looks like..


Code:
 public void writeXML(String fn) throws IOException {
 

         XMLEncoder encoder = new XMLEncoder(new BufferedOutputStream(
                 new FileOutputStream(fn)));
         encoder.writeObject(this);
         encoder.close();
 

         }

This is found in the 'model' class which takes user input and stores them into ArrayLists.

However, whenever I save in XML I get..

Code:
 <?xml version="1.0" encoding="UTF-8"?>
 <java version="1.7.0_09" class="java.beans.XMLDecoder">
  <object class="Model"/>
 </java>

I hope that's enough information regarding my issue, if any of you can help then I'll forever be thankful!

Thanks

Also, all of the code can be found here.
 
Soldato
Joined
23 Feb 2009
Posts
4,976
Location
South Wirral
Ok ... now I'm looking on a screen big enough to look at your pastebin post, I can see the Book class has two setAuthor() methods. One taking a single Author object and the other (posted above) that takes an array. However, the 'who' member is a single author, so the array version isn't going to make sense. You need to either:

- Remove it. Does your model need to support multiple authors of a single book ?
- Choose one author (e.g. the first one) from the array you're passing in and set 'who' to that
- Change the who member to be an array of authors (and change the single author setter to handle this)


At the moment, the "Book" bean is inconsistent and I think that's stuffing up the reflection/introspection used by the XMLEncoder class.
 
Soldato
OP
Joined
23 Dec 2010
Posts
3,483
Ok ... now I'm looking on a screen big enough to look at your pastebin post, I can see the Book class has two setAuthor() methods. One taking a single Author object and the other (posted above) that takes an array. However, the 'who' member is a single author, so the array version isn't going to make sense. You need to either:

- Remove it. Does your model need to support multiple authors of a single book ?
- Choose one author (e.g. the first one) from the array you're passing in and set 'who' to that
- Change the who member to be an array of authors (and change the single author setter to handle this)


At the moment, the "Book" bean is inconsistent and I think that's stuffing up the reflection/introspection used by the XMLEncoder class.

The book can only support one model.

I don't quite understand what you want me to do?
 
Associate
Joined
20 Jan 2013
Posts
280
Location
Shropshire
Your Book class has an Author,

private Author who;

but you have a setter method with an ArrayList as an argument which doesn't make sense. An instance of Book can only ever have 1 Author instance set to it.

The question is, is this setter just a mistake/error or did you intend for a Book to have multiple Authors?
 
Soldato
OP
Joined
23 Dec 2010
Posts
3,483
Your Book class has an Author,

private Author who;

but you have a setter method with an ArrayList as an argument which doesn't make sense. An instance of Book can only ever have 1 Author instance set to it.

The question is, is this setter just a mistake/error or did you intend for a Book to have multiple Authors?

I didn't want the book to have many authors.

I don't see where I've done that?
 
Associate
Joined
20 Jan 2013
Posts
280
Location
Shropshire
Ok, then as peterwalkley has suggested, something needs to be done regarding the "public void setAuthor(ArrayList<Author> authors)" method on the Book class.

in your original post you were setting

this.who = who;

which probably wont do anything at all as your are just pointing 'who' at it's self.
setting this.who = authors; wont work either as you are trying to assign a reference to an ArrayList to an Author object (which aren't of the same type).

However, you do already have a valid setter "public void setAuthor(Author who)", so just wondering what the need for overloading was for?
 
Soldato
OP
Joined
23 Dec 2010
Posts
3,483
Ok, then as peterwalkley has suggested, something needs to be done regarding the "public void setAuthor(ArrayList<Author> authors)" method on the Book class.

in your original post you were setting

this.who = who;

which probably wont do anything at all as your are just pointing 'who' at it's self.
setting this.who = authors; wont work either as you are trying to assign a reference to an ArrayList to an Author object (which aren't of the same type).

However, you do already have a valid setter "public void setAuthor(Author who)", so just wondering what the need for overloading was for?

So get rid of this.who = who;?
 
Soldato
Joined
30 Dec 2003
Posts
5,770
Location
London
I know nothing of Java, really... but the method appears to serialize a class with no public properties in it. authors and books are both private members.

I would hazard a guess that if there were public get/set methods for authors and books ArrayLists in Model, the serializer might find something to serialize. It will work by convention.
 
Associate
Joined
12 Nov 2012
Posts
1,075
Location
Gloucestershire, UK
Looking at the code, you are attempting to assign an arrayList of authors to a single instance, this will give you a type mismatch.

Your getAuthor() method with the arrayList parameter has a variable called authors, yet you are assigning a variable called who to this.who, in this instance there is no method parameter called who.

Code:
	public void setAuthor(ArrayList<Author> [b]authors[/b]) { 
        this.who = [b]who[/b] //who does not exists as a method parameter;
        //who is also a single instance of author, not a list of authors.
        //This is a type mismatch.
	}

It would appear you just copy/pasted the method then modified it this is one reason copy/pasting code is bad, any errors will just get replicated to multiple places.

That being said, your code looks a lot better than some of my early uni code :p
 
Soldato
OP
Joined
23 Dec 2010
Posts
3,483
Thanks for the complement, but I will say that some of the people here at Uni are absolutely amazing at programming - I'm nothing in comparison.

I'll just try my hardest to catch up.

I'll give that a go in a bit.
 
Soldato
Joined
30 Dec 2003
Posts
5,770
Location
London
Still got no public properties? Check my earlier post.

I think the setAuthor type mismatch, while incorrect, is a red herring. It will never be called.
 
Soldato
Joined
30 Dec 2003
Posts
5,770
Location
London
:)

As I alluded, I've not written any Java, so I'm not totally familiar. However a quick google seems to confirm my guess that XMLEncoder operates by convention - it will serialize/deserialize properties in a class by using getXXX and setXXX methods.

If you look at your Model class, you don't have any property get/set methods, so as far as XMLEncoder is concerned, it's empty. So you might now see why your output just has a line for an object called 'Model' and nothing else.

My guess is that if you added the following methods into Model so it looked like this, you might get a little more:

Code:
public class Model implements Serializable 
{
		private books = new ArrayList<Book>();
		private authors = new ArrayList<Author>();
		
                          {...}

		public ArrayList<Book> getBooks() {
			return books;
		}
		
		public void setBooks(ArrayList<Book> books) {
			this.books = books;
		}
		
		public ArrayList<Author> getAuthors() {
			return authors;
		}
		
		public void setAuthors(ArrayList<Author> authors) {
			this.authors = authors;
		}
                          
                          {...}
	}
 
Last edited:
Back
Top Bottom