Search code examples
javajsonxmljacksonfasterxml

no single-String constructor/factory method error on parsing xml to java object


I am trying to convert the xml response to java object but having error on parsing. I tried all the options but no success. The xml could have multiple tags. The error is basically coming when converting the xml tag to array object. My classes are :

Accounts Summary Reply:

public class AccountSummaryReply {
    @JacksonXmlProperty(localName = "AccountSubType")
    private String AccountSubType;

    @JacksonXmlProperty(localName = "WorkingBalance")
    private String WorkingBalance;

    @JacksonXmlProperty(localName = "AccountStatus")
    private String AccountStatus;

    @JacksonXmlProperty(localName = "AccountNumber")
    private String AccountNumber;

    @JacksonXmlProperty(localName = "BranchCode")
    private String BranchCode;

    @JacksonXmlProperty(localName = "AccountName")
    private String AccountName;

    @JacksonXmlProperty(localName = "OpenActualBalance")
    private String OpenActualBalance;

    @JacksonXmlProperty(localName = "Currency")
    private String Currency;

    @JacksonXmlProperty(localName = "IBAN")
    private String IBAN;

    @JacksonXmlProperty(localName = "AccountType")
    private String AccountType;

    public String getAccountSubType ()
    {
        return AccountSubType;
    }

    public void setAccountSubType (String AccountSubType)
    {
        this.AccountSubType = AccountSubType;
    }

    public String getWorkingBalance ()
    {
        return WorkingBalance;
    }

    public void setWorkingBalance (String WorkingBalance)
    {
        this.WorkingBalance = WorkingBalance;
    }

    public String getAccountStatus ()
    {
        return AccountStatus;
    }

    public void setAccountStatus (String AccountStatus)
    {
        this.AccountStatus = AccountStatus;
    }

    public String getAccountNumber ()
    {
        return AccountNumber;
    }

    public void setAccountNumber (String AccountNumber)
    {
        this.AccountNumber = AccountNumber;
    }

    public String getBranchCode ()
    {
        return BranchCode;
    }

    public void setBranchCode (String BranchCode)
    {
        this.BranchCode = BranchCode;
    }

    public String getAccountName ()
    {
        return AccountName;
    }

    public void setAccountName (String AccountName)
    {
        this.AccountName = AccountName;
    }

    public String getOpenActualBalance ()
    {
        return OpenActualBalance;
    }

    public void setOpenActualBalance (String OpenActualBalance)
    {
        this.OpenActualBalance = OpenActualBalance;
    }

    public String getCurrency ()
    {
        return Currency;
    }

    public void setCurrency (String Currency)
    {
        this.Currency = Currency;
    }

    public String getIBAN ()
    {
        return IBAN;
    }

    public void setIBAN (String IBAN)
    {
        this.IBAN = IBAN;
    }

    public String getAccountType ()
    {
        return AccountType;
    }

    public void setAccountType (String AccountType)
    {
        this.AccountType = AccountType;
    }

    @Override
    public String toString()
    {
        return "AccountSummaryReply [AccountSubType = "+AccountSubType+", WorkingBalance = "+WorkingBalance+", AccountStatus = "+AccountStatus+", AccountNumber = "+AccountNumber+", BranchCode = "+BranchCode+", AccountName = "+AccountName+", OpenActualBalance = "+OpenActualBalance+", Currency = "+Currency+", IBAN = "+IBAN+", AccountType = "+AccountType+"]";
    }}

OperativeAccountsReply :

public class OperativeAccountsReply {

    @JacksonXmlProperty(localName = "AccountSummaryReply")
    private AccountSummaryReply[] AccountSummaryReply;

    public AccountSummaryReply[] getAccountSummaryReply ()
    {
        return AccountSummaryReply;
    }

    public void setAccountSummaryReply (AccountSummaryReply[] AccountSummaryReply)
    {
        this.AccountSummaryReply = AccountSummaryReply;
    }

    @Override
    public String toString()
    {
        return "OperativeAccountsReply [AccountSummaryReply = "+AccountSummaryReply+"]";
    }
}

CustomerAccountsReply :

public class CustomerAccountsReply {

        @JacksonXmlProperty(localName = "FinanceAccountsReply")
        private FinanceAccountsReply FinanceAccountsReply;

        @JacksonXmlProperty(localName = "CustomerNumber")
        private String CustomerNumber;

        @JacksonXmlProperty(localName = "InvestmentAccountsReply")
        private InvestmentAccountsReply InvestmentAccountsReply;

        @JacksonXmlProperty(localName = "ReturnCode")
        private String ReturnCode;

        @JacksonXmlProperty(localName = "OperativeAccountsReply")
        private OperativeAccountsReply OperativeAccountsReply;

        @JacksonXmlProperty(localName = "ReferenceNum")
        private String ReferenceNum;

        @JacksonXmlProperty(localName = "ReturnText")
        private String ReturnText;

        public FinanceAccountsReply getFinanceAccountsReply ()
        {
            return FinanceAccountsReply;
        }

        public void setFinanceAccountsReply (FinanceAccountsReply FinanceAccountsReply)
        {
            this.FinanceAccountsReply = FinanceAccountsReply;
        }

        public String getCustomerNumber ()
        {
            return CustomerNumber;
        }

        public void setCustomerNumber (String CustomerNumber)
        {
            this.CustomerNumber = CustomerNumber;
        }

        public InvestmentAccountsReply getInvestmentAccountsReply ()
        {
            return InvestmentAccountsReply;
        }

        public void setInvestmentAccountsReply (InvestmentAccountsReply InvestmentAccountsReply)
        {
            this.InvestmentAccountsReply = InvestmentAccountsReply;
        }

        public String getReturnCode ()
        {
            return ReturnCode;
        }

        public void setReturnCode (String ReturnCode)
        {
            this.ReturnCode = ReturnCode;
        }

        public OperativeAccountsReply getOperativeAccountsReply ()
        {
            return OperativeAccountsReply;
        }

        public void setOperativeAccountsReply (OperativeAccountsReply OperativeAccountsReply)
        {
            this.OperativeAccountsReply = OperativeAccountsReply;
        }

        public String getReferenceNum ()
        {
            return ReferenceNum;
        }

        public void setReferenceNum (String ReferenceNum)
        {
            this.ReferenceNum = ReferenceNum;
        }

        public String getReturnText ()
        {
            return ReturnText;
        }

        public void setReturnText (String ReturnText)
        {
            this.ReturnText = ReturnText;
        }

        @Override
        public String toString()
        {
            return "CustomerAccountsReply [FinanceAccountsReply = "+FinanceAccountsReply+", CustomerNumber = "+CustomerNumber+", InvestmentAccountsReply = "+InvestmentAccountsReply+", ReturnCode = "+ReturnCode+", OperativeAccountsReply = "+OperativeAccountsReply+", ReferenceNum = "+ReferenceNum+", ReturnText = "+ReturnText+"]";
        }
    }

The code to parse the xml to the classes are :

public static AHBESBFetchAllAccountsFullResponse parseXMLResponseForGetAllAccounts(byte[] response)
            throws JsonParseException, JsonMappingException, IOException {
        ObjectMapper objectMapper;
        AHBESBFetchAllAccountsFullResponse getAllAccountsResponse = null;
        System.err.println(response);
        objectMapper = new XmlMapper();
        getAllAccountsResponse = objectMapper.readValue(StringUtils.toEncodedString(response, StandardCharsets.UTF_8),
                AHBESBFetchAllAccountsFullResponse.class);
        System.err.println(getAllAccountsResponse.getResponseBody().getCustomerAccountsReply().getCustomerNumber());
        return getAllAccountsResponse;
    }

The response xml is :

<HB_EAI_REPLY>
    <HB_EAI_HEADER>
        <MsgFormat> FULL.ACCOUNT.INQUIRY </MsgFormat>
        <MsgVersion>0000</MsgVersion>
        <RequestorId>HB</RequestorId>
        <RequestorChannelId>IB</RequestorChannelId>
        <RequestorUserId/>
        <RequestorLanguage>E</RequestorLanguage>
        <RequestorSecurityInfo/>
        <EaiReference>0</EaiReference>
        <ReturnCode>0000</ReturnCode>
    </HB_EAI_HEADER>
    <Reply>
        <CustomerAccountsReply>
            <ReferenceNum>20100407183503799</ReferenceNum>
            <CustomerNumber>1234567</CustomerNumber>
            <ReturnText>OK</ReturnText>
            <OperativeAccountsReply>
                <AccountSummaryReply >  
                    <AccountNumber>545545453</AccountNumber>
                    <IBAN>AE12345678901234567890123456789012</IBAN>
                    <AccountType> </AccountType>
                    <AccountSubType />  
                    <AccountStatus>SA</AccountStatus>
                    <BranchCode>AE0010004</BranchCode>
                    <AccountName> Mohammad </AccountName>
                    <Currency >011</Currency >
                    <OpenActualBalance/>
                    <WorkingBalance > </WorkingBalance >
                </AccountSummaryReply>
                <AccountSummaryReply>   
                    <AccountNumber>545545453</AccountNumber>
                    <IBAN>AE12345678901234567890123456789012</IBAN>
                    <AccountType>Mohammad</AccountType >
                    <AccountSubType />  
                    <AccountStatus>SA</AccountStatus >
                    <BranchCode>AE0010004</BranchCode>
                    <AccountName/>
                    <Currency>011</Currency >
                    <OpenActualBalance>00</OpenActualBalance >
                    <WorkingBalance>AED</WorkingBalance >
                </AccountSummaryReply>
                </OperativeAccountsReply>
                    <InvestmentAccountsReply>
                        <InvestmentContract>
                            <InvestmentContractNo>0903123243</InvestmentContractNo>
                            <InvestmentHolderName>This is the holder’s Name</InvestmentHolderName>
                                    <InvestmentAccountType>One Year Term Deposit</InvestmentAccountType>
                                    <InvestmentBranchCode>AE0010004</InvestmentBranchCode>
                                    <InvestmentCurrencyCode>AED</InvestmentCurrencyCode>
                                    <InvestmentAmount>100000</InvestmentAmount>
                                    <InvestmentOpenDate>20090207</InvestmentOpenDate>
                                    <MaturityDate>20100207</MaturityDate>
                                    <DepositTenor>12</DepositTenor>
                                    <CategoryID>21016</CategoryID>
                                </InvestmentContract>
                                <InvestmentContract>
                            <InvestmentContractNo>0903123243</InvestmentContractNo>
                            <InvestmentHolderName>This is the holder’s Name</InvestmentHolderName>
                                    <InvestmentAccountType>One Year Term Deposit</InvestmentAccountType>
                                    <InvestmentBranchCode>AE0010004</InvestmentBranchCode>
                                    <InvestmentCurrencyCode>AED</InvestmentCurrencyCode>
                                    <InvestmentAmount>100000</InvestmentAmount>
                                    <InvestmentOpenDate>20090207</InvestmentOpenDate>
                                    <MaturityDate>20100207</MaturityDate>
                                    <DepositTenor>12</DepositTenor>
                                    <CategoryID>21016</CategoryID>
                                </InvestmentContract>
                            </InvestmentAccountsReply>
                            <FinanceAccountsReply>
                                <FinanceContract>
                                    <LoanContractNumber>LD0831601635</LoanContractNumber>
                                    <FinanceHolderName>This is the name of Finance Holder</FinanceHolderName>
                                    <FinanceBranchCode>AE0010004</FinanceBranchCode>
                                    <FinanceCurrencyCode>AED</FinanceCurrencyCode>
                                    <FinanceOpenDate>20081106</FinanceOpenDate>
                                    <InstallmentAmount>11974</InstallmentAmount>
                                    <OutstandingDueAmount>1939858.9</OutstandingDueAmount>
                                    <InitialLoanAmount>1127100</InitialLoanAmount>
                                    <DueDate>20100701</DueDate>
                                    <RemainingNoOfInstallments>162</RemainingNoOfInstallments>
                                    <InitialNoOfInstallments>180</InitialNoOfInstallments>
                                    <LoanType>Retail Tawaruq</LoanType>
                                    <NumOfDaysPastDuedate>32</NumOfDaysPastDuedate>
                                </FinanceContract>
                                <FinanceContract>
                                    <LoanContractNumber>LD0909004393</LoanContractNumber>
                                    <FinanceHolderName>This is the name of Finance Holder</FinanceHolderName>
                                    <FinanceBranchCode>AE0010004</FinanceBranchCode>
                                    <FinanceCurrencyCode>AED</FinanceCurrencyCode>
                                    <FinanceOpenDate>20090329</FinanceOpenDate>
                                    <InstallmentAmount>-301732.95</InstallmentAmount>
                                    <OutstandingDueAmount>1360190.99</OutstandingDueAmount>
                                    <InitialLoanAmount>2025000</InitialLoanAmount>
                                    <DueDate>20100930</DueDate>
                                    <RemainingNoOfInstallments>2</RemainingNoOfInstallments>
                                    <InitialNoOfInstallments>3</InitialNoOfInstallments>
                                    <LoanType>Leasehold - Regular Forward Ijara</LoanType>
                                    <NumOfDaysPastDuedate>32</NumOfDaysPastDuedate>
                                </FinanceContract>
                                </FinanceAccountsReply>
                                <ReturnCode>0000</ReturnCode>
                            </CustomerAccountsReply>
                            </Reply>    
                            </HB_EAI_REPLY>

I am getting the following error :

Exception in thread "main" com.fasterxml.jackson.databind.JsonMappingException: Can not instantiate value of type [simple type, class com.omnia.pie.esb.outward.messages.accounts.AccountSummaryReply] from String value ('545545453'); no single-String constructor/factory method
 at [Source: java.io.StringReader@59494225; line: 1, column: 563] (through reference chain: com.omnia.pie.esb.outward.messages.accounts.AHBESBFetchAllAccountsFullResponse["Reply"]->com.omnia.pie.esb.outward.messages.accounts.AHBESBFetchAllAccountsResponseBody["CustomerAccountsReply"]->com.omnia.pie.esb.outward.messages.accounts.CustomerAccountsReply["OperativeAccountsReply"]->com.omnia.pie.esb.outward.messages.accounts.OperativeAccountsReply["AccountSummaryReply"]->Object[][0])
    at com.fasterxml.jackson.databind.JsonMappingException.from(JsonMappingException.java:148)
    at com.fasterxml.jackson.databind.DeserializationContext.mappingException(DeserializationContext.java:878)
    at com.fasterxml.jackson.databind.deser.ValueInstantiator._createFromStringFallbacks(ValueInstantiator.java:281)
    at com.fasterxml.jackson.databind.deser.std.StdValueInstantiator.createFromString(StdValueInstantiator.java:284)
    at com.fasterxml.jackson.databind.deser.BeanDeserializerBase.deserializeFromString(BeanDeserializerBase.java:1176)
    at com.fasterxml.jackson.databind.deser.BeanDeserializer._deserializeOther(BeanDeserializer.java:145)
    at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:136)
    at com.fasterxml.jackson.databind.deser.std.ObjectArrayDeserializer.deserialize(ObjectArrayDeserializer.java:156)
    at com.fasterxml.jackson.databind.deser.std.ObjectArrayDeserializer.deserialize(ObjectArrayDeserializer.java:17)
    at com.fasterxml.jackson.databind.deser.SettableBeanProperty.deserialize(SettableBeanProperty.java:520)
    at com.fasterxml.jackson.databind.deser.impl.FieldProperty.deserializeAndSet(FieldProperty.java:101)
    at com.fasterxml.jackson.databind.deser.BeanDeserializer.vanillaDeserialize(BeanDeserializer.java:258)
    at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:125)
    at com.fasterxml.jackson.databind.deser.SettableBeanProperty.deserialize(SettableBeanProperty.java:520)
    at com.fasterxml.jackson.databind.deser.impl.FieldProperty.deserializeAndSet(FieldProperty.java:101)
    at com.fasterxml.jackson.databind.deser.BeanDeserializer.vanillaDeserialize(BeanDeserializer.java:258)
    at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:125)
    at com.fasterxml.jackson.databind.deser.SettableBeanProperty.deserialize(SettableBeanProperty.java:520)
    at com.fasterxml.jackson.databind.deser.impl.MethodProperty.deserializeAndSet(MethodProperty.java:95)
    at com.fasterxml.jackson.databind.deser.BeanDeserializer.vanillaDeserialize(BeanDeserializer.java:258)
    at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:125)
    at com.fasterxml.jackson.databind.deser.SettableBeanProperty.deserialize(SettableBeanProperty.java:520)
    at com.fasterxml.jackson.databind.deser.impl.MethodProperty.deserializeAndSet(MethodProperty.java:95)
    at com.fasterxml.jackson.databind.deser.BeanDeserializer.vanillaDeserialize(BeanDeserializer.java:258)
    at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:125)
    at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:3736)
    at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:2726)
    at com.omnia.pie.esb.ws.ESBInterchangeControllerImpl.parseXMLResponseForGetAllAccounts(ESBInterchangeControllerImpl.java:190)
    at com.omnia.pie.esb.ws.ESBInterchangeControllerImpl.main(ESBInterchangeControllerImpl.java:147)

Solution

  • It seems the AccountSummaryReply array is unwrapped in your XML. It would normally appear like :

    <AccountSummaryReplies>
       <AccountSummaryReply>
          <AccountNumber>545545453</AccountNumber>
       </AccountSummaryReply>
       <AccountSummaryReply>
          <AccountNumber>545545454</AccountNumber>
       </AccountSummaryReply>
    </AccountSummaryReplies>
    

    You have to specify that an array appears unwrapped in XML:

    @JacksonXmlElementWrapper(useWrapping = false)
    @JacksonXmlProperty(localName = "AccountSummaryReply")
    private AccountSummaryReply[] AccountSummaryReply;
    

    As a side note consider configuring your XmlMapper with:

    mapper.setPropertyNamingStrategy(PropertyNamingStrategy.UPPER_CAMEL_CASE);
    

    which means that all properties names in XML start with upper case letter and allows skipping all the @JacksonXmlProperty(localName = ) annotations