Curious
Curious

Reputation: 82

how to fix class java.util.LinkedHashMap cannot be cast to class java.lang.String error

So, I am trying to build a report. The details of some certain type of users need to be written in an excel file. On hitting the endpoint it returns 500 with the following stacktrace.

java.lang.ClassCastException: class java.util.LinkedHashMap cannot be cast to class java.lang.String (java.util.LinkedHashMap and java.lang.String are in module java.base of loader 'bootstrap')
        at com.clever.bas.util.Helpers.lambda$writeToExcel$0(Helpers.java:73)
        at java.base/java.util.LinkedHashMap.forEach(LinkedHashMap.java:721)
        at com.clever.bas.util.Helpers.lambda$writeToExcel$1(Helpers.java:64)
     

Here is the helper class that is throwing the error

public static InputStream writeToExcel(Stream<UserProfile> data) throws Exception {

//        final Map<String, Transaction> transaction = data.collect(Collectors.toMap(Transaction::getId, Function.identity()));

//        System.out.println(transaction + " +++++>>>>>>");


        //Blank workbook
        try (XSSFWorkbook workbook = new XSSFWorkbook()) {

            //Create a blank sheet
            XSSFSheet sheet = workbook.createSheet("transaction report");


            AtomicInteger rowNum = new AtomicInteger(1);

            AtomicBoolean isHeaderSet = new AtomicBoolean(false);
            data.forEach(userProfile -> {
                if (!isHeaderSet.get()){
                    createHeader(userProfile, sheet);
                    isHeaderSet.set(true);
                }
                XSSFRow row = sheet.createRow(rowNum.getAndIncrement());

                ObjectMapper mapObject = new ObjectMapper();
                Map<String, Object> mapObj = mapObject.convertValue(userProfile, Map.class);


                AtomicInteger cellNum = new AtomicInteger();
                mapObj.forEach((key, value) -> {
                    XSSFCell cell = row.createCell(cellNum.getAndIncrement());
                    cell.setCellValue(key);
                    if (value instanceof Integer)
                        cell.setCellValue((Integer) value);
                    else if (value instanceof BigDecimal)
                        cell.setCellValue(((BigDecimal) value).doubleValue());
                    else if (value instanceof Long)
                        cell.setCellValue((Long) value);
                    else cell.setCellValue((String) value);

                });
            });

I have checked the internet and none of what I have seem so far seems to be solving my problems. There is a List in the models as seen below

public class UserProfile {


    @Id
    @ObjectId
    private String id;

    @JsonFormat(pattern="yyyy-MM-dd'T'HH:mm:ssZ")
    private final Date createdAt = new Date(System.currentTimeMillis());

    @JsonFormat(pattern="yyyy-MM-dd'T'HH:mm:ssZ")
    private final Date updatedAt = new Date(System.currentTimeMillis());


    private String agentId;

    @NotBlank
    private String firstName;

    @NotBlank
    private String lastName;

    @NotBlank
    @Email(message="Invalid email Address")
    private String email;

    @NotBlank
    @Size(min=11, max=14)
    private String phoneNumber;

    private String businessName;

    @Size(min=11, max=11)
    private String bvn;

    @Size(min=11, max=11)
    private String nin;

    @URL
    private String profilePicture;

    @URL
    private String utilityBill;

    @URL
    private String identityCard;

    private RoleGroup roleGroup;

    @Embedded
    private List<Role> roles;

    @ObjectId
    @JsonIgnore
    private List<String> roleIds;

    private String userType; // STAFF, AGENT, AGGREGATOR, PROSPECT

    public Types.Gender gender;

    private String referralCode;

    private String referral;

    @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd")
    private Date dateOfBirth;

    private Types.VerificationStatus verificationStatus;

    private Types.ApprovalStatus approvalStatus;

    private boolean enabled;

    private boolean verified = false;

    private String address;
    private String city;
    private String lga;
    private String state;
    private String terminalId;
    private String accountNumber;
    private Double msc;

    @JsonProperty(access = JsonProperty.Access.WRITE_ONLY)
    private String transactionPin;

    @Transient
    private boolean hasPin;


    public ClPrincipal toPrincipal() {
        ClPrincipal principal = new ClPrincipal();
        principal.setProfileId(this.id);
        principal.setUsername(this.email);
        principal.setFirstname(this.firstName);
        principal.setLastname(this.lastName);
        principal.setRoleGroup(this.roleGroup.getName());
        principal.setRoles(new ArrayList<>());
        return principal;
    }

    public UserByTerminalDTO toUserTerminalDto(){
        UserByTerminalDTO user = new UserByTerminalDTO();
        user.setUserID(this.id);
        user.setFirstName(this.firstName);
        user.setLastName(this.lastName);
        user.setMsc(this.msc);
        return user;
    }

    public String fullName(){
        return this.firstName + " " + this.lastName;
    }

    public boolean isHasPin() {
        return Objects.nonNull(this.transactionPin) && !this.transactionPin.trim().isEmpty();
    }

}

It is some of the details of this model UserProfile that I want to write into an excel sheet and make it available for download. How do you think i solve the problem. The major error is coming from these lines particularly the one in bold

AtomicInteger cellNum = new AtomicInteger();
                    mapObj.forEach((key, value) -> {
                        XSSFCell cell = row.createCell(cellNum.getAndIncrement());
                        cell.setCellValue(key);
                        if (value instanceof Integer)
                            cell.setCellValue((Integer) value);
                        else if (value instanceof BigDecimal)
                            cell.setCellValue(((BigDecimal) value).doubleValue());
                        else if (value instanceof Long)
                            cell.setCellValue((Long) value);
                        **else cell.setCellValue((String) value);**
    
                    });
                });

Upvotes: 0

Views: 3371

Answers (1)

Razvan Fulea
Razvan Fulea

Reputation: 447

You're making an assumption that for the else branch, the value can only be a String, but from the error it looks like it is in fact a LinkedHashMap.

Make sure that whatever data you work with, you also treat the case where the value is a Map and write that accordingly.

Upvotes: 1

Related Questions