views:

191

answers:

4
Map session = ActionContext.getContext().getSession();
session.put("user", user);

This code generates a warning: Type safety: The method put(Object, Object) belongs to the raw type Map. References to generic type Map should be parameterized.

Map<String, Serializable> session = (Map<String, Serializable>)ActionContext.getContext().getSession();
session.put("user", user);

This code generates a warning: Type safety: Unchecked cast from Map to Map.

The getSession method belongs to Struts2 so I can't modify it. I would like to avoid using @SuppressWarnings because other warnings can be useful.

I guess all Struts2 users in the world faced the same problem... is there an elegant solution?

A: 

what if you'll do it like that?

Map<String, Serializable> session = ActionContext.getContext().getSession();
zed_0xff
It gives another warning: Type safety: The expression of type Map needs unchecked conversion to conform to Map<String,Serializable>
Nicolas Raoul
+2  A: 

I don't think there's any other way but @SuppressWarnings("unchecked"). I believe you can put it just above the line in question, and it will only suppress that line.

Edit: you can also do Map<?, ?> session = ActionContext.getContext().getSession(); but I'm not sure how willing you are to do that; you won't be able to put anything into the map that way (since the compiler can't check the type of what you're putting), only read from it.

Andrei Fierbinteanu
The one-line SuppressWarnings works indeed :-)
Nicolas Raoul
+1  A: 

What version of Struts 2 (especially XWork) are you using? For me, your following code gives an error:

Map<String, Serializable> session = (Map<String, Serializable>)ActionContext.getContext().getSession();
session.put("user", user);

Cannot cast from Map<String,Object> to Map<String,Serializable>.

This, on the other hand, works and gives no warnings:

Map<String, Object> session = ActionContext.getContext().getSession();
Tommi
Don't it? I get a warning (or was it an error?) if I don't cast...
helios
I use 2.1.8.1 which is the latest version. Your suggestion gives this warning: Type safety: The expression of type Map needs unchecked conversion to conform to Map<String,Object>
Nicolas Raoul
http://struts.apache.org/2.1.8.1/struts2-core/apidocs/com/opensymphony/xwork2/ActionContext.html It seems that the 2.1.8.1 getSession should return a parameterized map. Are you sure it's properly installed and not using an older version previously installed?
Andrei Fierbinteanu
@Nicolas Raoul: Something is different in our environments then since I don't get a warning. I would still check what XWork version you're using.
Tommi
Indeed I actually had two versions installed and was mistakenly using an older one, sorry for the confusion, and thanks a lot for your help!
Nicolas Raoul
A: 

The safest, most efficient way to deal with this is probably:

Map<?, ?> session = ActionContext.getContext().getSession();

and then type cast the objects retrieved from the session map.

The @SuppressWarnings approach will actually result in compiled code that is identical, but the type cast will be implicit; i.e. it won't be easy to spot by looking at the source code.

Other more expensive alternatives include:

  • an entry by entry copy from the Map<?, ?> to a new Map<String, Serializable> instance casting the keys and values to String and Serializable respectively, or

  • a generic method like the following that performs the typecast safely.


@SuppressWarnings("unchecked")
public <K,V> Map<K,V> castMap(Map<?, ?> map, Class<K> kClass, Class<V> vClass) {
    for (Map.Entry<?, ?> entry : map.entrySet()) {
        kClass.cast(entry.getKey());
        vClass.cast(entry.getValue());
    }
    return (Map<K,V>) map;
}
Stephen C