Java classes do not construct bean properties if no matching set and get/is

RESOLVED FIXED

Status

Rhino
Core
RESOLVED FIXED
11 years ago
11 years ago

People

(Reporter: Marcello Bastéa-Forte, Unassigned)

Tracking

Details

Attachments

(3 attachments)

(Reporter)

Description

11 years ago
User-Agent:       Mozilla/5.0 (Windows; U; Windows NT 6.0; en-US; rv:1.8.1a3) Gecko/20060526 BonEcho/2.0a3
Build Identifier: Rhino CVS

It seems as if classes with either setFoo or getFoo but not both will not create beans.  I ran into this problem when working with HttpServletResponse:
http://tomcat.apache.org/tomcat-5.0-doc/servletapi/javax/servlet/http/HttpServletResponse.html

It has a setStatus() method but no getStatus() method, so I cannot write response.status = response.SC_OK without getting an exception:
org.mozilla.javascript.EvaluatorException: Java class "javax.servlet.http.HttpServletResponse" has no public instance field or method named "status".

If I write response.setStatus(response.SC_OK) it works fine.  

Further testing revealed that this seems to be a bug in the JavaMembers.reflect() if either a get or set method is missing for a particular property.

I propose that if only a get method is visible, the property is defined as readonly and if only a set method is visible, the property should at least have a setter method.

Reproducible: Always

Steps to Reproduce:
1. Add the following Java class to your java classpath:
public class Foo {

    public Foo() {
    }
    
    public void setA(Object o) {
        System.out.println("setA "+o);
    }
    public Object getA() {
        System.out.println("getA ");
        return null;
    }
    public void setB(Object o) {
        System.out.println("setB "+o);
    }
    public Object getC(Object o) {
        System.out.println("getC ");
        return null;
    }

}

2. Write a javascript that tests this:
var foo = new Packages.Foo();
var Rhino = { log: function (msg) {
  print("Rhino.log : "+msg+"\n");
}};
try {
	foo.a = 1;
} catch (ex) { Rhino.log(ex) }
try {
	foo.b = 2;
} catch (ex) { Rhino.log(ex) }
try {
	foo.c = 3;
} catch (ex) { Rhino.log(ex) }
try {
	Rhino.log('a: '+foo.a);
} catch (ex) { Rhino.log(ex) }
try {
	Rhino.log('b: '+foo.b);
} catch (ex) { Rhino.log(ex) }
try {
	Rhino.log('c: '+foo.c);
} catch (ex) { Rhino.log(ex) }

3. Run it
Actual Results:  
setA 1.0
Rhino.log: InternalError: Java class "Foo" has no public instance field or method named "b".
Rhino.log: InternalError: Java class "Foo" has no public instance field or method named "c".
getA 
Rhino.log: a: null
Rhino.log: b: undefined
Rhino.log: c: undefined

Expected Results:  
the foo.b = 2 line should not get an error, and the Rhino.log('c:' +foo.c) line should print null instead of undefined.
(Reporter)

Comment 1

11 years ago
Created attachment 228553 [details]
Java class demonstrating problem
(Reporter)

Comment 2

11 years ago
Created attachment 228556 [details] [diff] [review]
Potential fix?

I had made a mistake in my earlier post, if there is a get function and no set function, it did function correctly (I simply had written my get function in Foo.java incorrectly!).

However, the original problem (a set method but no get method) still applies.  This patch fixes the problem for me.

Comment 3

11 years ago
Reviewed and committed the fix - will be in 1.6R3
Status: NEW → RESOLVED
Last Resolved: 11 years ago
Resolution: --- → FIXED

Comment 4

11 years ago
(In reply to comment #3)
> Reviewed and committed the fix - will be in 1.6R3
> 

Now I'm experiencing a similar problem on 1.6R3! Now, when you have both the setter and the getter, the property is not added to the members. Stepping through the reflect() method, it seems that when the iteration encounters a getter, it registers the property with the "toAdd" map, but then, when it encounters the setter, it overrides it with a BeanProperty that holds a null getter.
Created attachment 233039 [details] [diff] [review]
Patch to fix the bean property regression

This patch should fix the problem in JavaMembers that results in some bean properties not being exposed properly in NativeJavaObjects.

Comment 6

11 years ago
Ok, I commited your fix to CVS HEAD - actually refactored it a bit, as there was some code duplication in there (for looking up both getXxx and isXxx), other than that I didn't change it. Thank you again, and give it a try sometime.
You need to log in before you can comment on or make changes to this bug.