XMLEncoder oddity


H

hiwa

Here is a test class Foo:
import java.io.*;

public class Foo implements Serializable{
private final static String _VALUE = "value";
private String value;

public Foo newInstance(){
final Foo f = new Foo();
f.value = _VALUE;
return f;
}

public String getValue(){return value;}
public void setValue(String v){value = v;}
}

And an encoder:
import java.beans.*;

public class XmlEnc{
public static void main(String[] args){
XMLEncoder enc = new XMLEncoder(System.out);
enc.writeObject(new Foo());
enc.close();
}
}

And we get exception:
java.lang.IllegalArgumentException: object is not an instance of
declaring class
Continuing ...
java.lang.Exception: XMLEncoder: discarding statement
XMLEncoder.writeObject(Foo);
Continuing ...
<?xml version="1.0" encoding="UTF-8"?>
<java version="1.6.0-ea" class="java.beans.XMLDecoder">
</java>

What I have done wrong here???
 
Ad

Advertisements

R

Roedy Green

java.lang.IllegalArgumentException: object is not an instance of
declaring class
Continuing ...
java.lang.Exception: XMLEncoder: discarding statement
XMLEncoder.writeObject(Foo);
Continuing ...
<?xml version="1.0" encoding="UTF-8"?>
<java version="1.6.0-ea" class="java.beans.XMLDecoder">
</java>

What I have done wrong here???

One puzzling thing is there is no line number for the exception. It is
not that you failed to provide it. XMLEncoder did.

I have no idea what that error message is trying to say, but I noticed
your JavaBean was missing a no-arg constructor and instead had a fancy
pants factory. I added an explicit no-arg constructor and removed
newInstance and off it went.

Why that worked puzzles me just as much as it does you. The
constructor should have been there by default.
 
R

Roedy Green

public Foo newInstance(){
final Foo f = new Foo();
f.value = _VALUE;
return f;

I see it now. That should be STATIC.

Any public instance methods have to follow the bean get/set pattern.
 
H

hiwa

I see it now. That should be STATIC.
Wow! RG is always the great savior.
But, here comes the next phase of the problem.

/* first Foo */
import java.io.*;

public class Foo implements Serializable{
private final static String _VALUE = "value";
private String value;

public static Foo newInstance(){
final Foo f = new Foo();
f.value = _VALUE;
return f;
}

public String getValue(){return value;}
public void setValue(String v){value = v;}
}

gives encode result:
<?xml version="1.0" encoding="UTF-8"?>
<java version="1.6.0-ea" class="java.beans.XMLDecoder">
<object class="Foo">
<void property="value">
<null/>
</void>
</object>
</java>

/* second Foo -- only a method name is changed,
* nothing else has changed -- */
import java.io.*;

public class Foo implements Serializable{
private final static String _VALUE = "value";
private String value;

public static Foo getDefaultInstance(){
final Foo f = new Foo();
f.value = _VALUE;
return f;
}

public String getValue(){return value;}
public void setValue(String v){value = v;}
}

gives encode result:
<?xml version="1.0" encoding="UTF-8"?>
<java version="1.6.0-ea" class="java.beans.XMLDecoder">
<object class="Foo"/>
</java>

I have read Sun documents How to Use XMLEncoder and
Redundancy Elimination. They don't help for this oddity.

Could this be a great JoBol's turn, or ...?
 
R

Roedy Green

I have read Sun documents How to Use XMLEncoder and
Redundancy Elimination. They don't help for this oddity.

Beans are supposed to have a garden variety constructor. XMLEncoder
can't glean the default values of the fields without one.

I think the way it works is it creates an empty bean using no-arg
constructor, executes each of the getters to find the default values,
then leaves them and default values when generating XML.

Your no-arg constructor fails to initialise "value" correctly.

Why are you using a factory method that does nothing that an ordinary
constructor cannot do?
 
H

hiwa

Why are you using a factory method that does nothing that an ordinary
constructor cannot do?
One of my friends is addicting himself to Factory design pattern and
I'm
helping worsening his addiction.

Mere change of a method name triggers the change of encode output.
It's a pure mystery.

I don't think method namd newInstance is reserved for JavaBeans spec.
 
Ad

Advertisements

R

Roedy Green

I don't think method namd newInstance is reserved for JavaBeans spec.

Yes but nobody but you knows about it. You need a proper no-arg
constructor for JavaBean work.

public Foo()
{
value = _VALUE;
}
 
H

hiwa

Yes but nobody but you knows about it. You need a proper no-arg
constructor for JavaBean work.
Mais, a nullary constructor should have been provided
as the default constructor. Our/your web applications
traditionally depend upon them without problem. In fact
new Foo() call doesn't generate any problem in the above
encoder class.

So I think this constructor issue has nothing to do with the
oddity described above.
 
R

Roedy Green

Mais, a nullary constructor should have been provided
as the default constructor.

The default no-arg constructor you get as a freebie does no
initialisation. You need one that sets the default for value
correctly such as I posted earlier.

You asked why you got two different XML exports. One presumed null was
the default for value, the other presumed "value".
 
H

hiwa

One presumed null was
the default for value, the other presumed "value".
Still I can't swallow the last lump.

The output:
<?xml version="1.0" encoding="UTF-8"?>
<java version="1.6.0-ea" class="java.beans.XMLDecoder">
<object class="Foo"/>
</java>

for an object of:
/* second Foo -- only a method name is changed,
* nothing else has changed -- */
import java.io.*;
public class Foo implements Serializable{
private final static String _VALUE = "value";
private String value;
public static Foo getDefaultInstance(){
final Foo f = new Foo();
f.value = _VALUE;
return f;
}
public String getValue(){return value;}
public void setValue(String v){value = v;}
}

is a proper result of redundancy elimination. I think I could
understand
that. But, in the output:
<?xml version="1.0" encoding="UTF-8"?>
<java version="1.6.0-ea" class="java.beans.XMLDecoder">
<object class="Foo">
<void property="value">
<null/>
</void>
</object>
</java>

for an object from same new Foo() for:
/* first Foo */
import java.io.*;
public class Foo implements Serializable{
private final static String _VALUE = "value";
private String value;
public static Foo newInstance(){
final Foo f = new Foo();
f.value = _VALUE;
return f;
}
public String getValue(){return value;}
public void setValue(String v){value = v;}
}

same redundancy is not eliminated. Why it is that?
Or, is my understading wrong in the first place?
 
R

Roedy Green

Still I can't swallow the last lump.

Fine. If you think you know better and you refuse to read the Javadoc
that explains this...

I am tired of beating this dead horse.
 
Ad

Advertisements

H

hiwa

dead horse
The method names newInstance and getDefaultInstance,
both are commonplace, arbitrary and ordinary identifiers.
They should have no special semantics for XMLEncoder
API. Then, why on earth their encode outputs differ?
Javadoc that explains this
Will you please give pointer for that?
The javadoc for XMLEncoder doesn't tell nothing for this
issue. Or, does it?
 
R

Roedy Green

The method names newInstance and getDefaultInstance,
both are commonplace, arbitrary and ordinary identifiers.
They should have no special semantics for XMLEncoder
API. Then, why on earth their encode outputs differ?

Please reread my previous posts.
 
H

hiwa

Please reread my previous posts.
Sorry. I can't find an answer for this issue in them.
This has nothing to do with constructor nor property initialization.
It's a quirk around difference in names of a class method.

Because no other people give replies here, I will try
another forum next week.

Thanks for keeping attention on this weird issue.
 
Ad

Advertisements


Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top