converting Object -HashMap to XMLObject - java

I have created a webservice which takes a HashMap as parameter.
I generated the stubs/skeletion using XMLBeans and I am trying to set the values in the parameter and pass it to the webservice.
The issue is:
I have the HashMap or List and API is expecting it to be XMLObject is there any conversion utility which can be useful to convert my value to XMLObject?

not sure about conversion, but I have successfully sent HashMap via webservice by wrapping the HashMap in an object like so:
class MapObject {
HashMap<String, String> myMap;
public MapObject(){}
public HashMap<String, String> getMap() {
return myMap;
}
public void setMyMap(HashMap<String, String> myMap) {
this.myMap = myMap;
}
}
Then just make your web service parameter type MapObject.

Related

Spotbugs + Java: may expose internal representation by storing an externally mutable object into QuestionPojo.map

Small question regarding a Spotbug finding I am having a hard time to fix please.
On this super simple POJO:
import java.util.Map;
public class QuestionPojo {
private final Map<String, String> map;
public QuestionPojo(Map<String, String> map) {
this.map = map;
}
public Map<String, String> getMap() {
return map;
}
#Override
public String toString() {
return "QuestionPojo{" +
"map=" + map +
'}';
}
}
I am getting flag on the map with may expose internal representation by storing an externally mutable object into QuestionPojo.map
One time on this.map = map;
Another one on the getter return map.
I tried invoking a possible clone() method, but it seems it is not supported in Map.
How do I fix this please?
Thank you
may expose internal representation by storing an externally mutable object into QuestionPojo.map
What this is telling you is that the internal state of an instance of this class can be changed outside the class.
For example:
Map<String, String> map = new HashMap<>();
map.put("hello", "world");
QuestionPojo qp = new QuestionPojo(map);
// Both of these lines change the map stored inside qp.
map.clear();
qp.getMap().put("silly", "silly");
As to whether this external change of state is important depends on the semantics of your class - in general it is undesirable, however, because it makes it hard to reason about its behavior, because the map can be changed from afar (i.e. anywhere that has a reference to the QuestionPojo, or the map).
The solution to this is defensive copying: take a copy of the map in the constructor:
public QuestionPojo(Map<String, String> map) {
this.map = new HashMap<>(map);
}
and return a copy of the map in the getter:
public Map<String, String> getMap() {
return new HashMap<>(map);
}
This means that nothing outside the class has access to the map stored inside the class.

Meaning of ? in Map<String, ?>

Method createBuilderFactory in javax.json needs argument of type Map<String, ?>
Generally, we have map with like Map<String, String>(some other data types in place of String)
But I didn't understand what does ? stands for. And in order to pass argument of type Map<String, ?>, how I should define the map.
Can someone please help me to understand this better?
In Java generics the ? stands for wildcard, which represent any object.
If you create a method that takes Map<String, ?> you are saying that you expect a Map that maps from String keys to any possible object values:
public static void main(String[] args) {
Map<String, Object> map1 = null;
Map<String, String> map2 = null;
test(map1);
test(map2);
}
private static void test(Map<String, ?> settings) {}
I had difficulties when I need to pass Map<String, ?> to my function, which was accepting Map<String, Object>. And this cut it:
Map<String, ?> mapQuestion = ...
mapObject = (Map<String, Object>)mapQuestion;

How to use a map with a generic enum type as function return type in Java

I am using an interface method that returns the map with these key, values.
public interface IParse<T> {
Map<String, T> parse(); //T is an enum type
}
Now in the implementation classes, I use the function parse with
public class TestClass1 implements IParse
{
public Map<String, EnumType1> parse()
{
Map<String, EnumType1> map1 = new HashMap<>();
// Logic to fill the map
return map1;
}
}
public class TestClass2 implements IParse
{
public Map<String, EnumType2> parse()
{
Map<String, EnumType2> map2 = new HashMap<>();
// Logic to fill the map
return map2;
}
}
and return the map containing appropriate enum type. But eclipse seems does not like it. One of the help options shows "Infer Generic Type Arguments".
Now in the above case, how do I use properly return the map without any type casting. Is there any other way I can use the interface method with a return value a map containing values as enum class types. Please give me an example on how to do this.
Please let me know if any further details are required.

GWT Autobean Codex reading a Map

I have a JSON map like:
{ "element":"value","element2":"value2",...}
With both key and value strings. I try to read it with an autobean and I get strange exceptions. It should be straightforward, shouldn't?
The error I'm getting is:
[ERROR] [project_name] - The java.util.Map parameterization is not simple, but the getConf method does not provide a delegate
I read the map like that:
final String jsObject = GeneralContextNativeReader.read("globalConf");
GlobalConfFactory globalConfFactory = GWT.create(GlobalConfFactory.class);
Map<String, String> globalConf = AutoBeanCodex.decode(globalConfFactory, Map.class, jsObject).as();
and the factory is defined as:
public interface GlobalConfFactory extends AutoBeanFactory {
AutoBean<Map<String, String>> globalConf();
}
What is wrong with that ?
AFAIK Maps and Lists and other non simple objects can only be reference types and not value types. See here for more details.
Changing the code to this should make it work:
public interface Data {
public Map<String,String>> getGlobalConf();
}
public interface DataFactory extends AutoBeanFactory {
AutoBean<Data> getData();
}
final String jsObject = GeneralContextNativeReader.read("globalConf");
DataFactory dataFactory = GWT.create(DataFactory.class);
Data data = AutoBeanCodex.decode(dataFactory, Data.class, jsObject).as();
Map<String, String> globalConf = data.getGlobalConf();
Your json string has to look something like that:
{"globalConf":{ "element":"value","element2":"value2",...}}
This can also happen if your AutoBean interface contains a static method (new in Java 8).

Pass a Map<String, String> to a method requiring Map<String, Object>

I have a method with the following signature
public static ActionDefinition reverse(String action, Map<String, Object> args)
And I have method that returns the following:
public static Map<String, String> toMap(String value)
Is there some way I can cast the output of toMap to be used in reverse, something like:
ActionDefinition ad = reverse("Action.method", toMap("param1=value1,param2=value2"));
I'd need to do something like
(Map<String, Object>) toMap("param1=value1,param2=value2");
but I couldn't fin the way to do it
I also tried with the following method
public static Map<String, String> toMap(String value) {
Map<String, Object> source = toMap(value);
Map<String, String> map = new LinkedHashMap<String, String>();
for(Map.Entry<String, Object> entry: source.entrySet()) {
map.put(entry.getKey(), (String) entry.getValue());
}
return map;
}
but I guess that due to type erasure, I get that the method is duplicated...
any idea?
--
edit
I forgot to state that I can't change reverse method, as many have suggested so far...
if you can change the method you wanna call to
public static ActionDefinition reverse(String action, Map<String, ? extends Object> args)
Change the method signature of reverse to use generics
public static ActionDefinition reverse(String action, Map<String, ? extends Object> args)
Cast it to simple (Map), but beware you are cheating.
You can always cast it to Map because it is one, and you can always feed a raw type into a method because of backwards compatibility, so casting a parametrized type to a raw one is always a way to convert it to any other parameters. But you should only do that when you know that it won't introduce a bug and if you have no sensible alternative.

Categories