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

Did you like this post or found it useful? Considering supporting this Blog to keep its web servers running, any amount helps! Thanks!
Have comments or feedback on what I wrote? Please share them below!
comments powered by Disqus
Other posts you may like...