2

I have a class like this:

import java.util.List;
import java.util.String;
import javax.xml.bind.annotation.XmlType;

@XmlType
public class Foo {
    private List<Foo> compound;
    private String bar; 

    // private method used internally to know 
    // if this is a compound instance
    private boolean isCompound() {
       return compound != null && compound.size() != 0;
    }

    // public setter for compound instance var
    public void setCompound(List<Foo> compound) {
        this.compound = compound;
    }

    // public getter for compound instance var
    public List<Foo> getCompound() {
        return compound;
    }

    public void setBar(String bar) {
        this.bar = bar;
    }

    public String getBar() {
        return bar;
    }
}

In normal use, this class behaves as you would expect. The methods getCompound and setCompound get and set the compound list. However, I'm using this class as an object that's passed in a web service built using JAX-WS. When the JAX-WS compiler sees this class, it ignores the setCompound and getCompound accessors, and the only property that appears in the XSD is bar.

After banging my head against the wall for most of the day, I decided to try changing the name of the private method isCompound to isACompound and suddenly everything worked as you'd expect. JAX-WS created the correct schema for the compound property.

What seems to be happening is that JAX-WS is seeing the isCompound method (even though it's private) and treating it as a getter with no corresponding setter and therefore ignoring the real public accessors for compound.

Is there anything in the Java Bean specification that says you can't have a private is<Something> method where <something> is also the name of a non-boolean property, which also has its own accessors? Surely anything using reflection on the class should simply ignore private methods?

mluisbrown
  • 14,448
  • 7
  • 58
  • 86
  • Try adding `@XmlAccessorType(XmlAccessType.FIELD)` to `Foo`. Also add `@XmlTransient` to `isCompound` to be safe. Oh, also, [it's pretty straightforward to access private members in a class](http://stackoverflow.com/questions/11483647/how-to-access-private-methods-and-private-data-members-via-reflection). – kolossus Apr 23 '14 at 21:13
  • Generally speaking it is a good idea to avoid creating custom methods called getX, setX or isX, if X is the name of a member field. It is generally accepted that these name formats are for getters and setters (isX being generally accepted as a getter for a boolean field). It appears your environment is confused by the naming convention and you solved the problem by changing the method name to something that is not confused with a getter. – Don Apr 25 '14 at 00:24
  • Yes, I know you can access private methods using reflection, but JAX-WS should ignore them, even if they have a getter/setter name format. – mluisbrown Apr 27 '14 at 11:27

1 Answers1

0

What happens if you change:

 return compound != null && compound.size() != 0;
 //To:
 private boolean isCompound() {
 boolean check = false;
 if(compound !=null && compound.size()!=0){
    check  = true;
 }else{
    check  =false;
 }
    return check;
 }

//or
@XmlAccessorType(XmlAccessType.NONE) on the class and @XmlElement and @XmlAttribute on the get/set methods.
Petro
  • 3,484
  • 3
  • 32
  • 59
  • The implementation of the method `isCompound` is irrelevant as far as this problem is concerned. Even if it were just `return true` it would make no difference. – mluisbrown Apr 22 '14 at 16:49
  • what about adding XmlAccessorType(XmlAccessType.NONE) on the class and XmlElement and XmlAttribute on the get/set methods. – Petro Apr 22 '14 at 17:33
  • I solved my problem by changing the name of the method name to `isACompound`. My question is not how to solve that problem, it's about why JAX-WS (or whatever it's using) isn't ignoring private methods, which it should be. – mluisbrown Apr 27 '14 at 11:30