Details
-
Bug
-
Status: Open
-
Critical
-
Resolution: Unresolved
-
1.2RC2
-
None
-
None
-
Windows XP, JDK 1.4.2_06
Description
Deserialization of SOAP(document/literal) went wrong because of Introspection Problem
We use a WSDL in mode document/literal/wrapped with complex datastructures defined
by XML schemata. If I send the SOAP request to the SOAP-Server we get a correct
SOAP Response, but the Deserialization goes wrong. I have modified the BeanDeserializer
with a work arround. More detailed information is explained later.
If the logging is switched on the following stacktrace is thrown:
12031 [main] ERROR org.apache.axis.client.Call - Exception:
org.xml.sax.SAXException: Invalid element in de.d2vodafone.eai.legokias.soapgenerated.ResultDetailsObject - Status
at org.apache.axis.encoding.ser.BeanDeserializer.onStartChild(BeanDeserializer.java:223)
at org.apache.axis.encoding.DeserializationContext.startElement(DeserializationContext.java:1031)
at org.apache.axis.message.SAX2EventRecorder.replay(SAX2EventRecorder.java:165)
at org.apache.axis.message.MessageElement.publishToHandler(MessageElement.java:1140)
at org.apache.axis.message.RPCElement.deserialize(RPCElement.java:238)
at org.apache.axis.message.RPCElement.getParams(RPCElement.java:386)
at org.apache.axis.client.Call.invoke(Call.java:2402)
at org.apache.axis.client.Call.invoke(Call.java:2301)
at org.apache.axis.client.Call.invoke(Call.java:1758)
at de.d2vodafone.eai.legokias.soapgenerated.LegoKiasBindingStub.getCustomerBANDetails(LegoKiasBindingStub.java:6
86)
at de.d2vodafone.eai.legokias.LegoKiasFacade.getCustomerDetails(LegoKiasFacade.java:86)
at de.d2vodafone.eai.legokias.test.GetCustomerBANTest.main(GetCustomerBANTest.java:35)
The problem is the detection of getter/setter. The java.beans.Introspection class is used to fill the map with detailed type
definition. The name of the PropertyDescription class is used as the key for these Map. I detected the following
getStatus() -> status
getBAN() -> BAN
In the WSDL I defined them as Status and BAN. If now the BeanDeserializer tries to deserialize the data in the
method "onStartChild()", it first tries to get detailed property definition. Because of the literal-Mode
the propertyMap is used to get the information. The localName is used as the key for the map.
In this special case the localName is "Status" but the entry in the map is registired as "status".
The first letter is low sensitive. Hence an exception is thrown because with "Status" no entry
in found.
I implemented a work around, that isn't really good but it works:
if (typeDesc != null)
{ // Lookup the name appropriately (assuming an unqualified // name for SOAP encoding, using the namespace otherwise) String fieldName = typeDesc.getFieldNameForElement(elemQName, isEncoded); propDesc = (BeanPropertyDescriptor)propertyMap.get(fieldName); fieldDesc = typeDesc.getFieldByName(fieldName); } if (propDesc == null) {
// look for a field by this name.
propDesc = (BeanPropertyDescriptor) propertyMap.get(localName);
// *************************************************************
// MY WORKARROUND
// *************************************************************
if(propDesc == null)
{ String k = localName.substring(0,1).toLowerCase() + localName.substring(1,localName.length()); propDesc = (BeanPropertyDescriptor) propertyMap.get(k); }}
The follwing class shows the result of the Introspection class
package de.d2vodafone.eai.legokias.test;
import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
public class IntrospectionTest {
private int status;
private String BAN;
public static void main(String[] args) {
try {
PropertyDescriptor[] props = Introspector.getBeanInfo(IntrospectionTest.class).getPropertyDescriptors();
int len = props.length;
for (int i=0; i < len; i++ )
{ System.out.println(props[i].getName()); }} catch (IntrospectionException e)
{ // TODO Auto-generated catch block e.printStackTrace(); } }
public String getBAN()
public void setBAN(String ban)
{ BAN = ban; }public int getStatus()
{ return status; }public void setStatus(int status)
{ this.status = status; }}
RESULT:
BAN
status
I hope the my information helps you to fix the problem. I think my workarround costs tomuch time at runtime.
With kind regards!
Andre Genser