7

JAXB is generating methods such as: isIsBuyNow() and isHasBuyNow() when I want isBuyNow() or hasBuyNow().

There are many many class methods being generated, so individually customizing the generated method names is not feasible.

Some sort of regex rule to customise the JAXB is the first thing that came to mind, but I can't find any such general way to change method names.

Kevin
  • 4,070
  • 4
  • 45
  • 67

3 Answers3

5

You can use an external bindings file to customize your property name. In order for JAXB to recognize the method as a property it must follow the convention of starting with get or is for boolean types.

schema.xsd

<?xml version="1.0" encoding="utf-8" ?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">

   <xs:complexType name="root">
      <xs:attribute name="is-buy-now" type="xs:boolean"/>
   </xs:complexType>

</xs:schema>

bindings.xml

In the bindings file below we have specified a property name for the XML attribute called is-buy-now:

<jxb:bindings 
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    xmlns:jxb="http://java.sun.com/xml/ns/jaxb"
    version="2.1">
    <jxb:bindings schemaLocation="is.xsd">
        <jxb:bindings node="//xs:complexType[@name='root']/xs:attribute[@name='is-buy-now']">
        <jxb:property name="buyNow"/>
        </jxb:bindings>
    </jxb:bindings>
</jxb:bindings>

XJC Call

The -b option is used to specify a bindings file:

xjc -d out -b bindings.xml schema.xsd

Root

As a result the following class will be generated with: isBuyNow and setBuyNow methods:

//
// This file was generated by the JavaTM Architecture for XML Binding(JAXB) Reference Implementation, vJAXB 2.1.10 in JDK 6 
// See <a href="http://java.sun.com/xml/jaxb">http://java.sun.com/xml/jaxb</a> 
// Any modifications to this file will be lost upon recompilation of the source schema. 
// Generated on: 2012.02.03 at 05:18:59 AM EST 
//


package generated;

import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlType;


/**
 * <p>Java class for root complex type.
 * 
 * <p>The following schema fragment specifies the expected content contained within this class.
 * 
 * <pre>
 * &lt;complexType name="root">
 *   &lt;complexContent>
 *     &lt;restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
 *       &lt;attribute name="is-buy-now" type="{http://www.w3.org/2001/XMLSchema}boolean" />
 *     &lt;/restriction>
 *   &lt;/complexContent>
 * &lt;/complexType>
 * </pre>
 * 
 * 
 */
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "root")
public class Root {

    @XmlAttribute(name = "is-buy-now")
    protected Boolean buyNow;

    /**
     * Gets the value of the buyNow property.
     * 
     * @return
     *     possible object is
     *     {@link Boolean }
     *     
     */
    public Boolean isBuyNow() {
        return buyNow;
    }

    /**
     * Sets the value of the buyNow property.
     * 
     * @param value
     *     allowed object is
     *     {@link Boolean }
     *     
     */
    public void setBuyNow(Boolean value) {
        this.buyNow = value;
    }

}

UPDATE

If you start from Java classes you can specify @XmlAccessorType(XmlAccessType.FIELD) to map to fields and name your methods as you choose:

@XmlAccessorType(XmlAccessType.FIELD)
public class Root {

    @XmlAttribute(name="has-buy-now")
    private boolean buyNow;

    public boolean hasBuyNow() {
        return buyNow;
    }

}
bdoughan
  • 147,609
  • 23
  • 300
  • 400
  • If there are say, 100 methods, is-buy-now, is-expired, is-reserve-met etc, it seems this solution would have me writing hundreds of lines in the bindings.xml file Is this the case, or have I missunderstood? – Kevin Feb 03 '12 at 23:18
  • With this approach you are correct. If you have many of these properties you could take advantage of the approach given by @KalebBrasee: http://stackoverflow.com/a/9123497/383861 – bdoughan Feb 04 '12 at 11:53
2

From the sounds of it you only need to change method names, not class names. You may be able to either:

  1. find an XJC plugin that allows this, or
  2. write an XJC plugin that does this

I doubt the first option exists (though you might get lucky), but the second option seems pretty straightforward. See this page for some posts on how to write your own.

Kaleb Brasee
  • 51,193
  • 8
  • 108
  • 113
  • You can customize the property name using a standard (JSR-222) external binding file, and don't require an external plug-in: http://stackoverflow.com/a/9127208/383861 – bdoughan Feb 03 '12 at 10:45
  • Please look at detailed answer https://stackoverflow.com/questions/21606248/jaxb-convert-non-ascii-characters-to-ascii-characters/21780020#21780020 how to write similar Naming plugin – Hubbitus Jan 27 '19 at 21:57
2

Before marching the plugin route. I would emphasize corercting your variables name. It should be as per Java Bean conventions. And JAXB should be working as per that only.

so if the variable is boolean, ist should idealy be buyNow. Respective getter method will become isBuyNow() only which you want. It would be matter of regenerating the mappings again. No regeex no custom find/replace as you (rightly) want :)

manocha_ak
  • 904
  • 7
  • 19
  • The schema I am using is 3rd party and I don't have the option of changing it, unfortunately. – Kevin Feb 03 '12 at 05:52
  • Ohh I should have guessed that :( – manocha_ak Feb 03 '12 at 06:43
  • 1
    You might be able to give a different propertyName as mentioned in customizingg property binbdings in tyhe liunk here - http://docs.oracle.com/cd/E17802_01/webservices/webservices/docs/2.0/tutorial/doc/JAXBUsing4.html#wp148590 – manocha_ak Feb 03 '12 at 06:51
  • +1 for Java Bean conventions and your link. I have an answer with a complete example if you are interested: http://stackoverflow.com/a/9127208/383861 – bdoughan Feb 03 '12 at 10:47