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

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


A quick disclaimer...

Although I put in a great effort into researching all the topics I cover, mistakes can happen. Use of any information from my blog posts should be at own risk and I do not hold any liability towards any information misuse or damages caused by following any of my posts.

All content and opinions expressed on this Blog are my own and do not represent the opinions of my employer (Oracle). Use of any information contained in this blog post/article is subject to this disclaimer.
Hi! You can search my blog here ⤵
NOTE: (2022) This Blog is no longer maintained and I will not be answering any emails or comments.

I am now focusing on Atari Gamer.