简体   繁体   中英

error SessionMap cannot be cast to java.util.HashMap

I am trying to store my HashMap value in session and then I am retrieving it using JSP but I am receiving an error saying

HTTP Status 500 - org.apache.struts2.dispatcher.SessionMap cannot be cast to java.util.HashMap

Any idea why I am getting that error?

package com.action;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.Statement;
import java.text.BreakIterator;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

import com.action.GetCon;




public class JanuaryAction implements SessionAware{
private String name;
Map abc = new HashMap();


public Map getAbc() {
return abc;
}

public void setAbc(Map abc) {
this.abc = abc;
}


public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}

@Override
public void setSession(Map abc) {
this.abc = (HashMap) abc;

}
public String execute() throws Exception{

String time=getName();
 /*   System.out.println(time);*/
if(time.equals("January 2013")){

abc.put(time,"'2013-01-01' AND OrderDate <= '2013-01-31'" );
}
else if(time.equals("February 2013")){
abc.put(time,"'2013-02-01' AND OrderDate <='2013-02-31'" );
}
else if(time.equals("March 2013")){
abc.put(time,"'2013-03-01' AND OrderDate <='2013-03-31'" );
}
else if(time.equals("April 2013")){
abc.put(time,"'2013-04-01' AND OrderDate <='2013-04-31'" );
}
else if(time.equals("May 2013")){
abc.put(time,"'2013-05-01' AND OrderDate <='2013-05-31'" );
}
else if(time.equals("June 2013")){
abc.put(time,"'2013-06-01' AND OrderDate <='2013-06-05'" );
}
String newtime=(String)abc.get(time);
   /* System.out.println(newtime);*/

Connection con = GetCon.getCon();
Statement statement = con.createStatement();
ResultSet resultset = statement.executeQuery("SELECT MarketPlace,OrderDate, ROUND(SUM(Total),2),  COUNT(*) , ROUND(ROUND(SUM(Total),2)/ COUNT(*),2) FROM vend_printed WHERE OrderDate >=" +newtime+ " GROUP BY OrderDate,MarketPlace") ;
Object value = abc.remove(time);

while(resultset.next()){

String marketplace = resultset.getString(1);

String orderdate = resultset.getString(2);

Double datamount = resultset.getDouble(3);
Integer count= resultset.getInt(4);

Double result=resultset.getDouble(5);

abc.put(0, marketplace);
abc.put(1, orderdate);
abc.put(2, datamount);
abc.put(3, count);
abc.put(4, result);}

return "success";
}}

In my JSP, I wanted to display the loop values one by one. so i am using this code now, but it is not displaying anything.

<s:property value="#session.0" /><br><br><br>
<s:property value="#session.1" /><br><br><br>
<s:property value="#session.2" /><br><br><br>
<s:property value="#session.3" /><br><br><br>
<s:property value="#session.4" /><br><br><br>   

Problem is here:

@Override
public void setSession(Map abc) {
  //abc is actually a SessionMap, which is not a HashMap !
  this.abc = (HashMap) abc;
}

because you suppose that abc is an HashMap , which is wrong. It is actually a SessionMap (that's what the error message says). SessionMap does not extends HashMap , it extends AbstractMap which directly extends Object .

See : http://struts.apache.org/release/2.0.x/struts2-core/apidocs/org/apache/struts2/dispatcher/SessionMap.html

Basically, when you implements SessionAware you suppose that the Map will be an HashMap , which is absolutely not guaranteed and is indeed not the case.

I suggest you to replace the attribute definition :

HashMap abc = new HashMap();

With:

private Map abc; //Don't initialize it as it is done by the setter.

The problem lies here:

@Override
public void setSession(Map abc) {
    this.abc = (HashMap) abc;
}

You are casting a Map which is an interface to HashMap , a concrete implementation. This cast is unsafe since you don't know for sure which type the abc is. It can be any of SessionMap , TreeMap , LinkedHashMap , etc.

Since the setSession has been defined to take a Map , so you should either use that Map or create a new one.

public class JanuaryAction implements SessionAware{
    private String name;
    Map abc = new HashMap(); // Use the interface Map instead of a concrete implementation

    @Override
    public void setSession(Map abc) {
        // this.abc = abc; // you can do this
        this.abc = new HashMap(abc); // prefer to do this
    }
}

This is a SessionAware implementation, use it

private Map<String, Object> session;

@Override
public void setSession(Map<String, Object> session) {
 this.session = session;
}

in the execute create a new collection with values and put into the session map. The problem with your code you are reusing the same variable abc that initially used to build the query. You should create another one and use the List instead of Map to keep the order of the items you want to iterate and display in JSP. Better to create and use the class that you should populate from the ResultSet and populate it into the list.

public class Market {
  private String marketplace;  
  private String orderdate;  
  private Double datamount;
  private Integer count;  
  private Double result;

  public String getMarketplace() {
    return marketplace;
  }

  public void setMarketplace(String marketplace) {
    this.marketplace = marketplace;
  }

  public String getOrderdate() {
    return orderdate;
  }

  public void setOrderdate(String orderdate) {
    this.orderdate = orderdate;
  }

  public Double getDatamount() {
    return datamount;
  }

  public void setDatamount(Double datamount) {
    this.datamount = datamount;
  }

  public Integer getCount() {
    return count;
  }

  public void setCount(Integer count) {
    this.count = count;
  }

  public Double getResult() {
    return result;
  }

  public void setResult(Double result) {
    this.result = result;
  }

  public Market(String marketplace, String orderdate, Double datamount, Integer count, Double result) {
    this.marketplace = marketplace;
    this.orderdate = orderdate;
    this.datamount = datamount;
    this.count = count;
    this.result = result;
  }

}   

create the property to hold the results

@Element(value = Market.class)
private List<Market> markets = new ArrayList<>();

public List<Market> getMarkets() {
  return markets;
}

public void setMarkets(List<Market> markets) {
  this.markets = markets;
}

to populate the list you should use this block, I don't know how do you use the connection, so I didn't close it.

Connection con = GetCon.getCon();
Statement statement = con.createStatement();
try {
  ResultSet resultset = statement.executeQuery("SELECT MarketPlace,OrderDate, ROUND(SUM(Total),2),  COUNT(*) , ROUND(ROUND(SUM(Total),2)/ COUNT(*),2) FROM vend_printed WHERE OrderDate >=" +newtime+ " GROUP BY OrderDate,MarketPlace") ;
  while(resultset.next()){
  markets.add(new Market(
    resultset.getString(1),
    resultset.getString(2),
    resultset.getDouble(3),
    resultset.getInt(4),
    resultset.getDouble(5)
  ));
  }
} finally {
  try {
    statement.close();
  } catch (SQLException e) {}
}

}

now to keep the results in session

session.put("markets", markets);

in the JSP use the iterator tag, and you are not required to iterate the session object, just get it from action.

<s:iterator value="markets">
  Marketplace: <s:property value="marketplace" /><br> 
  Orderdate: <s:property value="orderdate" /><br>  
  Datamount: <s:property value="datamount" /><br>
  Count: <s:property value="count" /><br>  
  Result: <s:property value="result" /><br>
  <hr>
</s:iterator>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM