[ 
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. Because formValue() is tried before 
valueOf(), it throws exception and valueOf() is never tried, despite of fact 
that it will convert the value correctly.
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);

The issue was found by [Jeroen Vlek 
https://issues.apache.org/jira/secure/ViewProfile.jspa?name=jeroenvlek].


  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 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. Because formValue() is tried before 
valueOf(), it throws exception and valueOf() is never tried, despite of fact 
that it will convert the value correctly.
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);



> 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. Because formValue() is tried before 
> valueOf(), it throws exception and valueOf() is never tried, despite of fact 
> that it will convert the value correctly.
> 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);
> The issue was found by [Jeroen Vlek 
> https://issues.apache.org/jira/secure/ViewProfile.jspa?name=jeroenvlek].



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

Reply via email to