You are viewing a plain text version of this content. The canonical link for it is here.
Posted to java-dev@axis.apache.org by Chris Williamson <ch...@wolfram.com> on 2002/10/30 16:24:48 UTC

MessageElement

I think I have found a few bugs in MessageElement.  Either that or I need an
explanation on how things work.  I am building up a SOAPEnvelope using
MessageElement's.  When I build the MessageElement, I set the name,
attributes, value, etc.  One specific attribute I set is the xsi:type.
Obviously this is an important attribute.  And the problem revolves around
that this attribute is set to a qualified name.

First I tried to use setType, but this does not seem to work.  If I use
setType and then call getType, it gets the right thing, but it does not add
it to the attributes when toString is called.  I looked through the output
method (which seems to handle serializing MessageElements into Strings) and
it does not appear that the type is ever added to the attributes or set in
any other way.  So when output is called, the type is not added (that I can
see).

Here is an example...

MessageElement element = new MessageElement();
element.setName(<name>);
element.setNamespaceURI(<ns>);
element.setType(new QName(<ns>,<localpart>));
System.out.println(element.toString());

Here is what probably should be done in the outputImpl method of
MessageElement...

context.serialize(new QName(namespaceURI, name),
                  attributes,
                  objectValue, typeQName, false, Boolean.TRUE);

rather than...

context.serialize(new QName(namespaceURI, name),
                  attributes,
                  objectValue, null, false, Boolean.TRUE);

So since the above didn't work I tried to add an attribute for it manually.
At first I tried to use addAttribute(ns, local, qname).  This adds the
attribute, and when you call it the first time, it works properly.  It adds
the namespace declaration and the attribute.  However, on subsequent calls,
it does not work, because it appears that the the namespace declaration is
added to the SerializationContext rather than to the MessageElemnt
Attributes.

Here is an example...

MessageElement element = new MessageElement();
element.setName(<name>);
element.setNamespaceURI(<ns>);
element@addAttribute("http://www.w3.org/2001/XMLSchema-instance","type", new
QName(<ns>, <localName>));
System.out.println(element.toString());
System.out.println(element.toString());

Here is the place in MessageElement that is useful...

        if (qNameAttrs != null) {
            for (int i = 0; i < qNameAttrs.size(); i++) {
                QNameAttr attr = (QNameAttr)qNameAttrs.get(i);
                QName attrName = attr.name;
                System.out.println("Attr.value: " +
context.qName2String(attr.value));
                addAttribute(attrName.getNamespaceURI(),
                             attrName.getLocalPart(),
                             context.qName2String(attr.value));
            }
            qNameAttrs = null;
        }

The key to this is the call to qName2String.  If you bounce around a bit
inside SerializationContext you will see that if the namespace does not
exist, it will create a new one and register it with the
SerializationContext, but not add it as an attibute or anything to the
MessageElement.  Then the qNameAttrs are set to null and that namespace
declaration is officially lost after leaving the SerializationContext.  The
namespace is not written back as an attribute, as the prefixed attribute is
above.  Perhaps the qName2String method should be in MessageElement.  But
regardless how you do it, those namespace declarations need to be persisted
past the SerializationContext.

Next I tried to add the type attribute a different way.  This time I decided
I would keep track of the namespace prefixes myself and add elements based
on my prefixes.  I added the type definition with
element.addAttribute("http://www.w3.org/2001/XMLSchema-instance", "type",
<prefix> + <localPart>).  Then I planned on adding the namespace declaration
with element.addNamespaceDeclaration(<prefix>, <namespaceURI).  For this the
first call is executed correctly, but the second call has problems.  The
namespace declarations are never added as attributes.

Here is an example...

MessageElement element = new MessageElement();
element.setName(<name>);
element.setNamespaceURI(<ns>);
element.addAttribute("http://www.w3.org/2001/XMLSchema-instance",
                     "type",
                     <prefix> + ":" + <localpart>);
element.addNamespaceDeclaration(<prefix>, <namespaceURI>);
System.out.println(element.toString());

Here is what probably should be done in the outputImpl method of
MessageElement...

            context.serialize(new QName(namespaceURI, name),
                              getCompleteAttributes(),
                              objectValue, null, false, Boolean.TRUE);

rather than...

            context.serialize(new QName(namespaceURI, name),
                              attributes,
                              objectValue, null, false, Boolean.TRUE);

Finally since I could not add a namespace declaration using the method, I
tried to do it by adding an attribute.  I used the addAttribute(new
PrefixedQName(Constants`NS_URI_XMLNS, prefix, "xmlns"),
<namespaceURI>);  However, this adds a new namespace declaration for xmlns
which I do not want.  And then it prefixes the attribute I am declaring with
something besides "xmlns".  This doesn't work.  There is not a good way to
add namespace declarations manually.  When you guys implement
getCompleteAttributes you use have access to the prefix parameter of the
addAttribute method from Attributes, but that parameter not available in the
addAttribute signature of MessageElement.

Here is an example...

MessageElement element = new MessageElement();
element.setName(<name>);
element.addAttribute(new PrefixedQName(Constants`NS_URI_XMLNS, prefix,
"xmlns"),
                     <namespaceURI>);
element.addAttribute("http://www.w3.org/2001/XMLSchema-instance",
                     "type",
                     <prefix> + ":" + <localpart>);
element.addNamespaceDeclaration(<prefix>, <namespaceURI>);
System.out.println(element.toString());

Please take a look at these problems with MessageElement and let me know if
I am way off base.  I would like to report these as bugs if they truly are.
They are important bugs to me.  It makes my application completely unusable
at the moment.

Chris Williamson