Axis
  1. Axis
  2. AXIS-2417

Deserialization fails if your schema defines arrays within arrays.

    Details

    • Type: Bug Bug
    • Status: Open
    • Priority: Blocker Blocker
    • Resolution: Unresolved
    • Affects Version/s: 1.3
    • Fix Version/s: None
    • Labels:
      None
    • Environment:
      Windows XP / Java 1.5

      Description

      See the element PSWorkflow of the attached schema as an example. If you define subcomponents as arrays and these subcomponents specify an attribute named "id", array deserialization may fail because the deserialization context registers fixups based on the ids (prependend by #). If like in the supplied example multiple arrays and array comonents define an "id" and the id of different components is the same, deserialization may fail because the fixups are only mapped by the "#id".

      The fixups should instead be mapped by a fully qualified name. In the fix that I supplied I use the ArrayClass from the registered deserializer as qualifier. See org.apache.axis.encoding.DeserializationContext.registerFixup(String, Deserializer):

      public void registerFixup(String href, Deserializer dser)
      {
      if (fixups == null)
      fixups = new HashMap();

      +++ String qualifier = "";
      +++ Vector targets = dser.getValueTargets();
      +++ if (targets != null && !targets.isEmpty())
      +++ {
      +++ if (targets.get(0) instanceof DeserializerTarget)
      +++ {
      +++ DeserializerTarget target = (DeserializerTarget) targets.get(0);
      +++ if (target != null && target.target instanceof ArrayDeserializer)
      +++ {
      +++ ArrayDeserializer arrayDser = (ArrayDeserializer) target.target;
      +++ ArrayDeserializer.ArrayListExtension listExtension =
      +++ (ArrayDeserializer.ArrayListExtension) arrayDser.getValue();
      +++ if (listExtension != null)
      +++

      { +++ Class destClass = listExtension.getDestClass(); +++ if (destClass != null) +++ qualifier = "-" + destClass.getName(); +++ }

      +++ }
      +++ }
      +++ }

      +++ Deserializer prev = (Deserializer) fixups.put(href + qualifier, dser);

      // There could already be a deserializer in the fixup list
      // for this href. If so, the easiest way to get all of the
      // targets updated is to move the previous deserializers
      // targets to dser.
      if (prev != null && prev != dser) {
      dser.moveValueTargets(prev);
      if (dser.getDefaultType() == null)

      { dser.setDefaultType(prev.getDefaultType()); }

      }
      }

      While debugging this problem, I noticed that you do that same thing for attachement references. I would assume that that code will have the same issue.

      I noted that you use the attributes "id" and "href" for attachements and fixups. Does this mean that attributes with these names are reserved for Axis? I have not found any documentation regarding my question.

      1. systemServices.xsd
        16 kB
        Martin Genhart
      2. DeserializationContext.java
        42 kB
        Martin Genhart
      3. BeanPropertyDescriptor.java
        9 kB
        Ross Mills
      4. ArrayDeserializer.java
        31 kB
        Ross Mills

        Activity

        Hide
        Martin Genhart added a comment -

        The PSWorkflow example I talk about in the bug description.

        Show
        Martin Genhart added a comment - The PSWorkflow example I talk about in the bug description.
        Hide
        Martin Genhart added a comment -

        The fix I made. I'm pretty sure that this if not the complete fix but if works for me for now.

        Show
        Martin Genhart added a comment - The fix I made. I'm pretty sure that this if not the complete fix but if works for me for now.
        Hide
        Ross Mills added a comment -

        I encountered the same problem, but the above fix did not seem to fix the problem. However, I think I found part of the reason that this problem is occurring.

        In com.apache.axis.excoding.ser.ArrayDeserializer, in the ArrayListExtension constructors, there is an attempt to check if the array is abstract...

        java.lang.reflect.Modifier.isAbstract(arrayClass.getModifiers())

        I found that on when running Axis on Windows, this function actually returns true even though the array class is not abstract. I created simple non-Axis test case with the following lines of code...

        public static void main(String[] args)
        {
        try

        { String arrayName = "[Lcom.dex.b2b.model.ResultRow;"; Class arrayClass = Class.forName(arrayName); if (arrayClass == null) throw new Exception("IT'S NULL"); if (arrayClass.isInterface()) throw new Exception("IT'S AN INTERFACE"); if (java.lang.reflect.Modifier.isAbstract(arrayClass.getModifiers())) throw new Exception("IT'S ABSTRACT"); System.out.println("EVERYTHING IS OK!"); }

        catch (Exception e)

        { e.printStackTrace(); }

        }

        ... and the following is my ResultRow class (please excuse the length)...

        package com.dex.b2b.model;

        public class ResultRow
        {
        private String level;
        private ResultRow[] childRows;
        private String data1;
        private String data2;
        private String data3;
        private String data4;
        private String data5;
        private String data6;
        private String data7;
        private String data8;
        private String data9;
        private String data10;
        private String data11;
        private String data12;
        private String data13;
        private String data14;
        private String data15;
        private String data16;
        private String data17;
        private String data18;
        private String data19;
        private String data20;
        private String data21;
        private String data22;
        private String data23;
        private String data24;
        private String data25;
        private String data26;
        private String data27;
        private String data28;
        private String data29;
        private String data30;
        private String data31;
        private String data32;
        private String data33;
        private String data34;
        private String data35;
        private String data36;
        private String data37;
        private String data38;
        private String data39;
        private String data40;
        private String data41;
        private String data42;
        private String data43;
        private String data44;
        private String data45;
        private String data46;
        private String data47;
        private String data48;
        private String data49;
        private String data50;
        private String data51;
        private String data52;
        private String data53;
        private String data54;
        private String data55;
        private String data56;
        private String data57;
        private String data58;
        private String data59;
        private String data60;
        private String data61;
        private String data62;
        private String data63;
        private String data64;
        private String data65;
        private String data66;
        private String data67;
        private String data68;
        private String data69;
        private String data70;
        private String data71;
        private String data72;
        private String data73;
        private String data74;
        private String data75;

        public ResultRow()
        {
        }

        public String getLevel()

        { return level; }

        public void setLevel(String level)

        { this.level = level; }

        public ResultRow[] getChildRows()

        { return childRows; }

        public void setChildRows(ResultRow[] childRows)

        { this.childRows = childRows; }

        public String getData1()

        { return data1; }

        public void setData1(String data1)

        { this.data1 = data1; }

        public String getData2()

        { return data2; }

        public void setData2(String data2)

        { this.data2 = data2; }

        public String getData3()

        { return data3; }

        public void setData3(String data3)

        { this.data3 = data3; }

        public String getData4()

        { return data4; }

        public void setData4(String data4)

        { this.data4 = data4; }

        public String getData5()

        { return data5; }

        public void setData5(String data5)

        { this.data5 = data5; }

        public String getData6()

        { return data6; }

        public void setData6(String data6)

        { this.data6 = data6; }

        public String getData7()

        { return data7; }

        public void setData7(String data7)

        { this.data7 = data7; }

        public String getData8()

        { return data8; }

        public void setData8(String data8)

        { this.data8 = data8; }

        public String getData9()

        { return data9; }

        public void setData9(String data9)

        { this.data9 = data9; }

        public String getData10()

        { return data10; }

        public void setData10(String data10)

        { this.data10 = data10; }

        public String getData11()

        { return data11; }

        public void setData11(String data11)

        { this.data11 = data11; }

        public String getData12()

        { return data12; }

        public void setData12(String data12)

        { this.data12 = data12; }

        public String getData13()

        { return data13; }

        public void setData13(String data13)

        { this.data13 = data13; }

        public String getData14()

        { return data14; }

        public void setData14(String data14)

        { this.data14 = data14; }

        public String getData15()

        { return data15; }

        public void setData15(String data15)

        { this.data15 = data15; }

        public String getData16()

        { return data16; }

        public void setData16(String data16)

        { this.data16 = data16; }

        public String getData17()

        { return data17; }

        public void setData17(String data17)

        { this.data17 = data17; }

        public String getData18()

        { return data18; }

        public void setData18(String data18)

        { this.data18 = data18; }

        public String getData19()

        { return data19; }

        public void setData19(String data19)

        { this.data19 = data19; }

        public String getData20()

        { return data20; }

        public void setData20(String data20)

        { this.data20 = data20; }

        public String getData21()

        { return data21; }

        public void setData21(String data21)

        { this.data21 = data21; }

        public String getData22()

        { return data22; }

        public void setData22(String data22)

        { this.data22 = data22; }

        public String getData23()

        { return data23; }

        public void setData23(String data23)

        { this.data23 = data23; }

        public String getData24()

        { return data24; }

        public void setData24(String data24)

        { this.data24 = data24; }

        public String getData25()

        { return data25; }

        public void setData25(String data25)

        { this.data25 = data25; }

        public String getData26()

        { return data26; }

        public void setData26(String data26)

        { this.data26 = data26; }

        public String getData27()

        { return data27; }

        public void setData27(String data27)

        { this.data27 = data27; }

        public String getData28()

        { return data28; }

        public void setData28(String data28)

        { this.data28 = data28; }

        public String getData29()

        { return data29; }

        public void setData29(String data29)

        { this.data29 = data29; }

        public String getData30()

        { return data30; }

        public void setData30(String data30)

        { this.data30 = data30; }

        public String getData31()

        { return data31; }

        public void setData31(String data31)

        { this.data31 = data31; }

        public String getData32()

        { return data32; }

        public void setData32(String data32)

        { this.data32 = data32; }

        public String getData33()

        { return data33; }

        public void setData33(String data33)

        { this.data33 = data33; }

        public String getData34()

        { return data34; }

        public void setData34(String data34)

        { this.data34 = data34; }

        public String getData35()

        { return data35; }

        public void setData35(String data35)

        { this.data35 = data35; }

        public String getData36()

        { return data36; }

        public void setData36(String data36)

        { this.data36 = data36; }

        public String getData37()

        { return data37; }

        public void setData37(String data37)

        { this.data37 = data37; }

        public String getData38()

        { return data38; }

        public void setData38(String data38)

        { this.data38 = data38; }

        public String getData39()

        { return data39; }

        public void setData39(String data39)

        { this.data39 = data39; }

        public String getData40()

        { return data40; }

        public void setData40(String data40)

        { this.data40 = data40; }

        public String getData41()

        { return data41; }

        public void setData41(String data41)

        { this.data41 = data41; }

        public String getData42()

        { return data42; }

        public void setData42(String data42)

        { this.data42 = data42; }

        public String getData43()

        { return data43; }

        public void setData43(String data43)

        { this.data43 = data43; }

        public String getData44()

        { return data44; }

        public void setData44(String data44)

        { this.data44 = data44; }

        public String getData45()

        { return data45; }

        public void setData45(String data45)

        { this.data45 = data45; }

        public String getData46()

        { return data46; }

        public void setData46(String data46)

        { this.data46 = data46; }

        public String getData47()

        { return data47; }

        public void setData47(String data47)

        { this.data47 = data47; }

        public String getData48()

        { return data48; }

        public void setData48(String data48)

        { this.data48 = data48; }

        public String getData49()

        { return data49; }

        public void setData49(String data49)

        { this.data49 = data49; }

        public String getData50()

        { return data50; }

        public void setData50(String data50)

        { this.data50 = data50; }

        public String getData51()

        { return data51; }

        public void setData51(String data51)

        { this.data51 = data51; }

        public String getData52()

        { return data52; }

        public void setData52(String data52)

        { this.data52 = data52; }

        public String getData53()

        { return data53; }

        public void setData53(String data53)

        { this.data53 = data53; }

        public String getData54()

        { return data54; }

        public void setData54(String data54)

        { this.data54 = data54; }

        public String getData55()

        { return data55; }

        public void setData55(String data55)

        { this.data55 = data55; }

        public String getData56()

        { return data56; }

        public void setData56(String data56)

        { this.data56 = data56; }

        public String getData57()

        { return data57; }

        public void setData57(String data57)

        { this.data57 = data57; }

        public String getData58()

        { return data58; }

        public void setData58(String data58)

        { this.data58 = data58; }

        public String getData59()

        { return data59; }

        public void setData59(String data59)

        { this.data59 = data59; }

        public String getData60()

        { return data60; }

        public void setData60(String data60)

        { this.data60 = data60; }

        public String getData61()

        { return data61; }

        public void setData61(String data61)

        { this.data61 = data61; }

        public String getData62()

        { return data62; }

        public void setData62(String data62)

        { this.data62 = data62; }

        public String getData63()

        { return data63; }

        public void setData63(String data63)

        { this.data63 = data63; }

        public String getData64()

        { return data64; }

        public void setData64(String data64)

        { this.data64 = data64; }

        public String getData65()

        { return data65; }

        public void setData65(String data65)

        { this.data65 = data65; }

        public String getData66()

        { return data66; }

        public void setData66(String data66)

        { this.data66 = data66; }

        public String getData67()

        { return data67; }

        public void setData67(String data67)

        { this.data67 = data67; }

        public String getData68()

        { return data68; }

        public void setData68(String data68)

        { this.data68 = data68; }

        public String getData69()

        { return data69; }

        public void setData69(String data69)

        { this.data69 = data69; }

        public String getData70()

        { return data70; }

        public void setData70(String data70)

        { this.data70 = data70; }

        public String getData71()

        { return data71; }

        public void setData71(String data71)

        { this.data71 = data71; }

        public String getData72()

        { return data72; }

        public void setData72(String data72)

        { this.data72 = data72; }

        public String getData73()

        { return data73; }

        public void setData73(String data73)

        { this.data73 = data73; }

        public String getData74()

        { return data74; }

        public void setData74(String data74)

        { this.data74 = data74; }

        public String getData75()

        { return data75; }

        public void setData75(String data75)

        { this.data75 = data75; }

        }

        ... and here is the output, when I run the code above...

        java.lang.Exception: IT'S ABSTRACT

        ... it appears from the Java Spec that checking if an array is abstract is not supported. From the spec for java.lang.Class getModifiers...

        If this object represents an array class, a primitive type or void, then its final modifier is always true and its interface modifier is always false. The values of its other modifiers are not determined by this specification.

        ... I removed this check from the Axis code. However, despite this change, this problem continues. I desperately need this resolved. I'm hoping that this little discovery might be a little push in the right direction toward a real solution.

        Show
        Ross Mills added a comment - I encountered the same problem, but the above fix did not seem to fix the problem. However, I think I found part of the reason that this problem is occurring. In com.apache.axis.excoding.ser.ArrayDeserializer, in the ArrayListExtension constructors, there is an attempt to check if the array is abstract... java.lang.reflect.Modifier.isAbstract(arrayClass.getModifiers()) I found that on when running Axis on Windows, this function actually returns true even though the array class is not abstract. I created simple non-Axis test case with the following lines of code... public static void main(String[] args) { try { String arrayName = "[Lcom.dex.b2b.model.ResultRow;"; Class arrayClass = Class.forName(arrayName); if (arrayClass == null) throw new Exception("IT'S NULL"); if (arrayClass.isInterface()) throw new Exception("IT'S AN INTERFACE"); if (java.lang.reflect.Modifier.isAbstract(arrayClass.getModifiers())) throw new Exception("IT'S ABSTRACT"); System.out.println("EVERYTHING IS OK!"); } catch (Exception e) { e.printStackTrace(); } } ... and the following is my ResultRow class (please excuse the length)... package com.dex.b2b.model; public class ResultRow { private String level; private ResultRow[] childRows; private String data1; private String data2; private String data3; private String data4; private String data5; private String data6; private String data7; private String data8; private String data9; private String data10; private String data11; private String data12; private String data13; private String data14; private String data15; private String data16; private String data17; private String data18; private String data19; private String data20; private String data21; private String data22; private String data23; private String data24; private String data25; private String data26; private String data27; private String data28; private String data29; private String data30; private String data31; private String data32; private String data33; private String data34; private String data35; private String data36; private String data37; private String data38; private String data39; private String data40; private String data41; private String data42; private String data43; private String data44; private String data45; private String data46; private String data47; private String data48; private String data49; private String data50; private String data51; private String data52; private String data53; private String data54; private String data55; private String data56; private String data57; private String data58; private String data59; private String data60; private String data61; private String data62; private String data63; private String data64; private String data65; private String data66; private String data67; private String data68; private String data69; private String data70; private String data71; private String data72; private String data73; private String data74; private String data75; public ResultRow() { } public String getLevel() { return level; } public void setLevel(String level) { this.level = level; } public ResultRow[] getChildRows() { return childRows; } public void setChildRows(ResultRow[] childRows) { this.childRows = childRows; } public String getData1() { return data1; } public void setData1(String data1) { this.data1 = data1; } public String getData2() { return data2; } public void setData2(String data2) { this.data2 = data2; } public String getData3() { return data3; } public void setData3(String data3) { this.data3 = data3; } public String getData4() { return data4; } public void setData4(String data4) { this.data4 = data4; } public String getData5() { return data5; } public void setData5(String data5) { this.data5 = data5; } public String getData6() { return data6; } public void setData6(String data6) { this.data6 = data6; } public String getData7() { return data7; } public void setData7(String data7) { this.data7 = data7; } public String getData8() { return data8; } public void setData8(String data8) { this.data8 = data8; } public String getData9() { return data9; } public void setData9(String data9) { this.data9 = data9; } public String getData10() { return data10; } public void setData10(String data10) { this.data10 = data10; } public String getData11() { return data11; } public void setData11(String data11) { this.data11 = data11; } public String getData12() { return data12; } public void setData12(String data12) { this.data12 = data12; } public String getData13() { return data13; } public void setData13(String data13) { this.data13 = data13; } public String getData14() { return data14; } public void setData14(String data14) { this.data14 = data14; } public String getData15() { return data15; } public void setData15(String data15) { this.data15 = data15; } public String getData16() { return data16; } public void setData16(String data16) { this.data16 = data16; } public String getData17() { return data17; } public void setData17(String data17) { this.data17 = data17; } public String getData18() { return data18; } public void setData18(String data18) { this.data18 = data18; } public String getData19() { return data19; } public void setData19(String data19) { this.data19 = data19; } public String getData20() { return data20; } public void setData20(String data20) { this.data20 = data20; } public String getData21() { return data21; } public void setData21(String data21) { this.data21 = data21; } public String getData22() { return data22; } public void setData22(String data22) { this.data22 = data22; } public String getData23() { return data23; } public void setData23(String data23) { this.data23 = data23; } public String getData24() { return data24; } public void setData24(String data24) { this.data24 = data24; } public String getData25() { return data25; } public void setData25(String data25) { this.data25 = data25; } public String getData26() { return data26; } public void setData26(String data26) { this.data26 = data26; } public String getData27() { return data27; } public void setData27(String data27) { this.data27 = data27; } public String getData28() { return data28; } public void setData28(String data28) { this.data28 = data28; } public String getData29() { return data29; } public void setData29(String data29) { this.data29 = data29; } public String getData30() { return data30; } public void setData30(String data30) { this.data30 = data30; } public String getData31() { return data31; } public void setData31(String data31) { this.data31 = data31; } public String getData32() { return data32; } public void setData32(String data32) { this.data32 = data32; } public String getData33() { return data33; } public void setData33(String data33) { this.data33 = data33; } public String getData34() { return data34; } public void setData34(String data34) { this.data34 = data34; } public String getData35() { return data35; } public void setData35(String data35) { this.data35 = data35; } public String getData36() { return data36; } public void setData36(String data36) { this.data36 = data36; } public String getData37() { return data37; } public void setData37(String data37) { this.data37 = data37; } public String getData38() { return data38; } public void setData38(String data38) { this.data38 = data38; } public String getData39() { return data39; } public void setData39(String data39) { this.data39 = data39; } public String getData40() { return data40; } public void setData40(String data40) { this.data40 = data40; } public String getData41() { return data41; } public void setData41(String data41) { this.data41 = data41; } public String getData42() { return data42; } public void setData42(String data42) { this.data42 = data42; } public String getData43() { return data43; } public void setData43(String data43) { this.data43 = data43; } public String getData44() { return data44; } public void setData44(String data44) { this.data44 = data44; } public String getData45() { return data45; } public void setData45(String data45) { this.data45 = data45; } public String getData46() { return data46; } public void setData46(String data46) { this.data46 = data46; } public String getData47() { return data47; } public void setData47(String data47) { this.data47 = data47; } public String getData48() { return data48; } public void setData48(String data48) { this.data48 = data48; } public String getData49() { return data49; } public void setData49(String data49) { this.data49 = data49; } public String getData50() { return data50; } public void setData50(String data50) { this.data50 = data50; } public String getData51() { return data51; } public void setData51(String data51) { this.data51 = data51; } public String getData52() { return data52; } public void setData52(String data52) { this.data52 = data52; } public String getData53() { return data53; } public void setData53(String data53) { this.data53 = data53; } public String getData54() { return data54; } public void setData54(String data54) { this.data54 = data54; } public String getData55() { return data55; } public void setData55(String data55) { this.data55 = data55; } public String getData56() { return data56; } public void setData56(String data56) { this.data56 = data56; } public String getData57() { return data57; } public void setData57(String data57) { this.data57 = data57; } public String getData58() { return data58; } public void setData58(String data58) { this.data58 = data58; } public String getData59() { return data59; } public void setData59(String data59) { this.data59 = data59; } public String getData60() { return data60; } public void setData60(String data60) { this.data60 = data60; } public String getData61() { return data61; } public void setData61(String data61) { this.data61 = data61; } public String getData62() { return data62; } public void setData62(String data62) { this.data62 = data62; } public String getData63() { return data63; } public void setData63(String data63) { this.data63 = data63; } public String getData64() { return data64; } public void setData64(String data64) { this.data64 = data64; } public String getData65() { return data65; } public void setData65(String data65) { this.data65 = data65; } public String getData66() { return data66; } public void setData66(String data66) { this.data66 = data66; } public String getData67() { return data67; } public void setData67(String data67) { this.data67 = data67; } public String getData68() { return data68; } public void setData68(String data68) { this.data68 = data68; } public String getData69() { return data69; } public void setData69(String data69) { this.data69 = data69; } public String getData70() { return data70; } public void setData70(String data70) { this.data70 = data70; } public String getData71() { return data71; } public void setData71(String data71) { this.data71 = data71; } public String getData72() { return data72; } public void setData72(String data72) { this.data72 = data72; } public String getData73() { return data73; } public void setData73(String data73) { this.data73 = data73; } public String getData74() { return data74; } public void setData74(String data74) { this.data74 = data74; } public String getData75() { return data75; } public void setData75(String data75) { this.data75 = data75; } } ... and here is the output, when I run the code above... java.lang.Exception: IT'S ABSTRACT ... it appears from the Java Spec that checking if an array is abstract is not supported. From the spec for java.lang.Class getModifiers... If this object represents an array class, a primitive type or void, then its final modifier is always true and its interface modifier is always false. The values of its other modifiers are not determined by this specification. ... I removed this check from the Axis code. However, despite this change, this problem continues. I desperately need this resolved. I'm hoping that this little discovery might be a little push in the right direction toward a real solution.
        Hide
        Ross Mills added a comment -

        From Ross Mills - part of the fix for this problem

        Show
        Ross Mills added a comment - From Ross Mills - part of the fix for this problem
        Hide
        Ross Mills added a comment -

        This is main part of the fix

        Show
        Ross Mills added a comment - This is main part of the fix
        Hide
        Ross Mills added a comment -

        I was able to make changes to the code that fixed this problem for me. The change was actually pretty small. The updated code has been attached.

        Show
        Ross Mills added a comment - I was able to make changes to the code that fixed this problem for me. The change was actually pretty small. The updated code has been attached.

          People

          • Assignee:
            Unassigned
            Reporter:
            Martin Genhart
          • Votes:
            1 Vote for this issue
            Watchers:
            2 Start watching this issue

            Dates

            • Created:
              Updated:

              Development