cuizhennan / snakeyaml

Automatically exported from code.google.com/p/snakeyaml
Apache License 2.0
1 stars 0 forks source link

"No JavaBean properties..." an Error? #116

Closed GoogleCodeExporter closed 9 years ago

GoogleCodeExporter commented 9 years ago
What steps will reproduce the problem?
1. Compile and run the attached code

What is the expected output? What do you see instead?

I would expect, maybe:

!!Feature
chugger: !!Feature$PipelinedChugger {}

Instead, I see:

Exception in thread "main" org.yaml.snakeyaml.error.YAMLException: No JavaBean 
properties found in Feature$PipelinedChugger
        at org.yaml.snakeyaml.introspector.PropertyUtils.getPropertiesMap(PropertyUtils.java:80)
        at org.yaml.snakeyaml.introspector.PropertyUtils.createPropertySet(PropertyUtils.java:106)
        at org.yaml.snakeyaml.introspector.PropertyUtils.getProperties(PropertyUtils.java:95)
        at org.yaml.snakeyaml.introspector.PropertyUtils.getProperties(PropertyUtils.java:87)
        at org.yaml.snakeyaml.representer.Representer.getProperties(Representer.java:246)
        at org.yaml.snakeyaml.representer.Representer$RepresentJavaBean.representData(Representer.java:49)
        at org.yaml.snakeyaml.representer.BaseRepresenter.representData(BaseRepresenter.java:114)
        at org.yaml.snakeyaml.representer.Representer.representJavaBeanProperty(Representer.java:125)
        at org.yaml.snakeyaml.representer.Representer.representJavaBean(Representer.java:83)
        at org.yaml.snakeyaml.representer.Representer$RepresentJavaBean.representData(Representer.java:49)
        at org.yaml.snakeyaml.representer.BaseRepresenter.representData(BaseRepresenter.java:114)
        at org.yaml.snakeyaml.representer.BaseRepresenter.represent(BaseRepresenter.java:69)
        at org.yaml.snakeyaml.Yaml.dumpAll(Yaml.java:249)
        at org.yaml.snakeyaml.Yaml.dumpAll(Yaml.java:218)
        at org.yaml.snakeyaml.Yaml.dump(Yaml.java:206)
        at Feature.main(Feature.java:31)

What version of SnakeYAML are you using? On what Java version?

snakeyaml-1.9-SNAPSHOT
java version "1.6.0_20"                                                         

OpenJDK Runtime Environment (IcedTea6 1.9.7) (6b20-1.9.7-0ubuntu1~10.04.1)      

OpenJDK 64-Bit Server VM (build 19.0-b09, mixed mode)

Please provide any additional information below. (Often a failing test is
the best way to describe the problem.)

I'm not really sure this is a bug, but I don't see why having no JavaBean 
properties is necessarily an error, or how I would go about making my various 
interface implementations serialize properly (maybe adding a dummy public 
field?).

Original issue reported on code.google.com by elkn...@gmail.com on 16 May 2011 at 7:35

Attachments:

GoogleCodeExporter commented 9 years ago
SnakeYAML needs to know how to serialize/deserialize stateful Java instances. 
SnakeYAML defines some rules for known classes (Integer, String etc). All other 
classes are treated as JavaBeans if nothing else is specified.
This is exactly what happens in this case. The instances are not JavaBeans and 
there is no explicit description what to do with the instances.
It is not an error to have no properties. But it an error to serialize an 
instance with no data to serialize without any explanation to the parser. In 
the same way if you need to serialize 'java.io.File' you may wish to include or 
exclude its content. But it should be explicit definition and not a wild guess 
of the parser.

Original comment by py4fun@gmail.com on 17 May 2011 at 11:48

GoogleCodeExporter commented 9 years ago
While I agree that the parser should not be making a wild guess, I believe that 
it is already making a guess to some degree.  In the default mode, when the 
serializer/parser assumes an object is a JavaBean, it will ignore private 
fields as though their values don't matter without giving any sort of error.  
So long as there is at least one public field or JavaBean property, the parser 
has no issues with ignoring the rest of the object state that is not publicly 
accessible.  Of course, the developer is on his own if he does such a thing... 
but it is still a guess made by the parser.

In my situation, however, I know that the object that I'm trying to serialize 
should have no problems being treated in the default manner.  A thorough 
inspection of the object's fields, like what is done for the switch case of 
BeanAccess.FIELD (PropertyUtils:50-58, only also checking Modifier.isPublic) 
can determine that some objects have no fields whatsoever, so that the parser 
could know this too, without guessing.  In the end, the only information of 
value to me for some interface implementations is the virtual method table that 
dispatches the call, and that's encoded in the class name.

Is a JavaBean not a JavaBean simply because it has no instance data (besides 
the VMT)?

Anyhow, as we've both mentioned, there are ways around this issue.  It's just 
that I think the check that is being done and throwing the exception is not 
accurate enough.  I would recommend throwing the exception in the case where 
you can guarantee some state is being missed: some fields are not public and 
there are no set/get methods.  Unfortunately, that test may cause some users' 
code to fail when currently it does not.

Original comment by elkn...@gmail.com on 17 May 2011 at 2:04

GoogleCodeExporter commented 9 years ago
1)
> I believe that it is already making a guess to some degree.

If you find the current "guess" as inappropriate please create an issue and we 
can discuss it separately

2)
>like what is done for the switch case of BeanAccess.FIELD

Using BeanAccess.FIELD is an _explicit_ action and users should understand what 
is happening.
We may introduce another explicit action to indicate that no properties is a 
normal state. But it does not mean that the current situation is an error

3)
> Is a JavaBean not a JavaBean simply because it has no instance data (besides 
the VMT)?
I do not think this is the proper place to discuss that is a JavaBean and what 
is not. At the moment SnakeYAML trusts 'java.beans.Introspector.getBeanInfo()' 
(unfortunately it does not work the same across different JDKs)

4)
> I would recommend throwing the exception in the case where you can guarantee 
> some state is being missed: some fields are not public and there are no 
> set/get methods.  Unfortunately, that test may cause some users' code to fail 
> when currently it does not.

Private fields without public access methods do not violate the JavaBean spec. 
I do not understand why it should throw an exception

Original comment by py4fun@gmail.com on 23 May 2011 at 1:55

GoogleCodeExporter commented 9 years ago
I imagine we're misunderstanding one another, and you're right, this is not a 
good place to discuss this.

Original comment by elkn...@gmail.com on 23 May 2011 at 2:01

GoogleCodeExporter commented 9 years ago

Original comment by py4fun@gmail.com on 23 May 2011 at 3:09

GoogleCodeExporter commented 9 years ago
possible patch attached...

Original comment by elkn...@gmail.com on 8 Jun 2011 at 6:36

Attachments:

GoogleCodeExporter commented 9 years ago
Issue is re-open due to discussion in 
https://groups.google.com/forum/#!topic/snakeyaml-core/-sRma0bgCnM/discussion

I have put your patch to a clone: http://code.google.com/r/py4fun-emptybean/

The change is accepted without modifications 
(http://code.google.com/r/py4fun-emptybean/source/detail?r=af3bbeafef0df3deb554a
0858fea634806e724f8)
A weird test case is added just to see how it works.

I have removed one failing test because it was merely testing that an empty 
JavaBean must not be dumped.
But one failing test is left (in RepresenterTest). I think the test proves 
there is a regression. A JavaBean is dumped as if it is empty, but it is not. 
Failure to get a property must not cause an empty bean to be serialized. 
Instead, an exception is expected. We shall investigate the cause of the 
failure.

Original comment by py4fun@gmail.com on 9 Jun 2011 at 8:27

GoogleCodeExporter commented 9 years ago
Sorry, the failing test was not caused by your patch. (I am afraid it reveals a 
bug in SnakeYAML and it must be treated separately).
The fix has been promoted to the master source repository.
Feel free to test the latest SNAPSHOT:
https://oss.sonatype.org/content/groups/public/org/yaml/snakeyaml/1.9-SNAPSHOT/

Original comment by py4fun@gmail.com on 9 Jun 2011 at 9:50

GoogleCodeExporter commented 9 years ago
The fix will be delivered in version 1.9

Original comment by py4fun@gmail.com on 10 Jun 2011 at 1:15