Uploaded image for project: 'CXF'
  1. CXF
  2. CXF-5722

JAXB generated Enum throws IllegalArgumentException by unmarshalling as @QueryParam

    XMLWordPrintableJSON

    Details

    • Type: Bug
    • Status: Closed
    • Priority: Major
    • Resolution: Fixed
    • Affects Version/s: 3.0.0-milestone2
    • Fix Version/s: 3.0
    • Component/s: JAX-RS
    • Labels:
      None
    • Estimated Complexity:
      Unknown

      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 .

        Attachments

          Issue Links

            Activity

              People

              • Assignee:
                ashakirin Andrei Shakirin
                Reporter:
                ashakirin Andrei Shakirin
              • Votes:
                1 Vote for this issue
                Watchers:
                4 Start watching this issue

                Dates

                • Created:
                  Updated:
                  Resolved: