You are viewing a plain text version of this content. The canonical link for it is here.
Posted to issues@cxf.apache.org by "Andrei Shakirin (JIRA)" <ji...@apache.org> on 2014/05/01 10:24:14 UTC

[jira] [Updated] (CXF-5722) JAXB generated Enum throws IllegalArgumentException by unmarshalling as @QueryParam

     [ https://issues.apache.org/jira/browse/CXF-5722?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ]

Andrei Shakirin updated CXF-5722:
---------------------------------

    Description: 
By processing request with Query parameter, InjectionUtils tries to recognize and instantiate parameter class.
In case of Enum parameter class, InjectionUtils.handleParameter() method calls in loop following methods: "fromString", "fromValue", "valueOf" using reflection. If method returns null, it tries the next one:

        if (result == null) {
            // check for valueOf(String) static methods
            String[] methodNames = cls.isEnum() 
                ? new String[] {"fromString", "fromValue", "valueOf"} 
                : new String[] {"valueOf", "fromString"};
            for (String mName : methodNames) {   
                result = evaluateFactoryMethod(value, cls, pType, mName);
                if (result != null) {
                    break;
                }
            }

The problem is that factory methods in JAXB generated Enum behaves differently:
- valueOf accepts enum identifier (not value)
- fromValue accepts enum value
Both methods throws IllegalArgumentException by worng argument and do not return null, how current code expecting.
As a result following method throws IllegalArgumentException:
1) method:
    @GET
    @Path("/enum/")
    Response checkEnum(@QueryParam("car") CarType car);

2) generated enum:
@XmlRootElement(name = "Car")
@XmlType(name = "carType")
@XmlEnum
public enum CarType {

    @XmlEnumValue("Audi")
    AUDI("Audi"),
    @XmlEnumValue("Golf")
    GOLF("Golf"),
    BMW("BMW");
    private final String value;

    CarType(String v) {
        value = v;
    }

    public String value() {
        return value;
    }

    public static CarType fromValue(String v) {
        for (CarType c: CarType.values()) {
            if (c.value.equals(v)) {
                return c;
            }
        }
        throw new IllegalArgumentException(v);
    }
}

3) call:
customerService.checkEnum(CarType.AUDI);


  was:
By processing request with Query parameter, InjectionUtils tries to recognize and instantiate parameter class.
In case of Enum parameter class, InjectionUtils.handleParameter() method calls in loop following methods: "fromString", "fromValue", "valueOf" using reflection. If method returns null, it tries the next one:

        if (result == null) {
            // check for valueOf(String) static methods
            String[] methodNames = cls.isEnum() 
                ? new String[] {"fromString", "fromValue", "valueOf"} 
                : new String[] {"valueOf", "fromString"};
            for (String mName : methodNames) {   
                result = evaluateFactoryMethod(value, cls, pType, mName);
                if (result != null) {
                    break;
                }
            }

The problem is that JAXB generated Enum doesn't returns null, but throws IllegalArgumentException in fromValue() if argument is in wrong case. 
As a result following method throws IllegalArgumentException:
    @GET
    @Path("/enum/")
    Response checkEnum(@QueryParam("car") CarType car);

for generated bean:
@XmlRootElement(name = "Car")
@XmlType(name = "carType")
@XmlEnum
public enum CarType {

    @XmlEnumValue("Audi")
    AUDI("Audi"),
    @XmlEnumValue("Golf")
    GOLF("Golf"),
    BMW("BMW");
    private final String value;

    CarType(String v) {
        value = v;
    }

    public String value() {
        return value;
    }

    public static CarType fromValue(String v) {
        for (CarType c: CarType.values()) {
            if (c.value.equals(v)) {
                return c;
            }
        }
        throw new IllegalArgumentException(v);
    }
}


> JAXB generated Enum throws IllegalArgumentException by unmarshalling as @QueryParam
> -----------------------------------------------------------------------------------
>
>                 Key: CXF-5722
>                 URL: https://issues.apache.org/jira/browse/CXF-5722
>             Project: CXF
>          Issue Type: Bug
>          Components: JAX-RS
>    Affects Versions: 3.0.0-milestone2
>            Reporter: Andrei Shakirin
>            Assignee: Andrei Shakirin
>
> By processing request with Query parameter, InjectionUtils tries to recognize and instantiate parameter class.
> In case of Enum parameter class, InjectionUtils.handleParameter() method calls in loop following methods: "fromString", "fromValue", "valueOf" using reflection. If method returns null, it tries the next one:
>         if (result == null) {
>             // check for valueOf(String) static methods
>             String[] methodNames = cls.isEnum() 
>                 ? new String[] {"fromString", "fromValue", "valueOf"} 
>                 : new String[] {"valueOf", "fromString"};
>             for (String mName : methodNames) {   
>                 result = evaluateFactoryMethod(value, cls, pType, mName);
>                 if (result != null) {
>                     break;
>                 }
>             }
> The problem is that factory methods in JAXB generated Enum behaves differently:
> - valueOf accepts enum identifier (not value)
> - fromValue accepts enum value
> Both methods throws IllegalArgumentException by worng argument and do not return null, how current code expecting.
> As a result following method throws IllegalArgumentException:
> 1) method:
>     @GET
>     @Path("/enum/")
>     Response checkEnum(@QueryParam("car") CarType car);
> 2) generated enum:
> @XmlRootElement(name = "Car")
> @XmlType(name = "carType")
> @XmlEnum
> public enum CarType {
>     @XmlEnumValue("Audi")
>     AUDI("Audi"),
>     @XmlEnumValue("Golf")
>     GOLF("Golf"),
>     BMW("BMW");
>     private final String value;
>     CarType(String v) {
>         value = v;
>     }
>     public String value() {
>         return value;
>     }
>     public static CarType fromValue(String v) {
>         for (CarType c: CarType.values()) {
>             if (c.value.equals(v)) {
>                 return c;
>             }
>         }
>         throw new IllegalArgumentException(v);
>     }
> }
> 3) call:
> customerService.checkEnum(CarType.AUDI);



--
This message was sent by Atlassian JIRA
(v6.2#6252)