Igor Kromin |   Consultant. Coder. Blogger. Tinkerer. Gamer.

NOTE: This article is 3 years or older so its information may no longer be relevant. Read on at your own discretion! Comments for this article have automatically been locked, refer to the FAQ for more details.
I've noticed something curious while testing some web services recently. The keys and values in the HashMap object that's passed as an IN parameter to the web service were all being turned into nulls. If I passed one key/value pair, I'd get one key/value pair of nulls, if I passed two key/value pairs, I'd get a pair of null/null, and so on. I did eventually track down the problem and fixed it, but it has been an interesting issue to come across.

I created a test method that simply had one IN parameter that was the HashMap. Inside the method, I logged the keys and values that were passed to me...
 Java
@WebMethod
public void testMethod(
@WebParam(mode = WebParam.Mode.IN, name = "map")
@XmlElement(required = true) HashMap inputMap)
{
LOG.info(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>");
Set keys = inputMap.keySet();
for (Object key : keys) {
LOG.info(">> " + key + " = " + inputMap.get(key));
}
LOG.info(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>");
}


This was the kind of output being produced...
 Debug Output
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>> [key: null] = [value: null]
>> [key: null] = [value: null]
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>


When I looked into the XSDs associated with the WSDL generated for the web service, I noticed something strange, the key and value had xsd:anyType for its data type.
 XSD
<xsd:element name="map">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="entry" minOccurs="0" maxOccurs="unbounded">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="key" type="xsd:anyType" minOccurs="0"/>
<xsd:element name="value" type="xsd:anyType" minOccurs="0"/>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
</xsd:sequence>
</xsd:complexType>
</xsd:element>




This made be look at my WebMethod again. I realised that the HashMap was defined as untyped. Once I changed the definition to specify <String,String> as the key/value types the whole thing started to behave as expected.

The output became...
 Debug Output
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
>> key2 = value2
>> key1 = value1
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>



The XSD also changed to...
 XSD
<xsd:element name="map">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="entry" minOccurs="0" maxOccurs="unbounded">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="key" type="xsd:string" minOccurs="0"/>
<xsd:element name="value" type="xsd:string" minOccurs="0"/>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
</xsd:sequence>
</xsd:complexType>
</xsd:element>


The type="xsd:string" is what's important here. Looks like JAX-WS cannot process HashMaps that are not typed. Once an explicit type is specified, everything works correctly.

So in a nutshell, if using a HashMap in your WebMethod, be sure to type it correctly. In the end I changed my WebMethod definition to this:
 Java
@WebMethod
public void testMethod(
@WebParam(mode = WebParam.Mode.IN, name = "map")
@XmlElement(required = true) HashMap<String, String> inputMap)
{
...
}


-i

Skip down to comments...
Hope you found this post useful...

...so please read on! I love writing articles that provide beneficial information, tips and examples to my readers. All information on my blog is provided free of charge and I encourage you to share it as you wish. There is a small favour I ask in return however - engage in comments below, provide feedback, and if you see mistakes let me know.

If you want to show additional support and help me pay for web hosting and domain name registration, donations, no matter how small, are always welcome!

Use of any information contained in this blog post/article is subject to this disclaimer.
 
comments powered by Disqus
Other posts you may like...