Hi,
This is part of my schema (the whole thing is quite complex and inline
in a WSDL document):
<xsd:schema
targetNamespace="http://groupgti.com/esb/jobengines/email/service/GroupGtiSupportSystem/EmailSchedulerTarget"
xmlns:tns="http://groupgti.com/esb/jobengines/email/service/GroupGtiSupportSystem/EmailSchedulerTarget"
attributeFormDefault="qualified"
elementFormDefault="qualified">
<xsd:element name="ScheduledEmailQueryRequest"
type="tns:ScheduledEmailQueryRequestType"></xsd:element>
<xsd:element name="ScheduledEmailQueryResponse"
type="tns:ScheduledEmailQueryResponseType"></xsd:element>
...
<xsd:complexType name="ScheduledEmailQueryResponseType">
<xsd:sequence>
<xsd:element name="Message"
type="tns:EmailMessageDefinition" maxOccurs="unbounded"
minOccurs="0"></xsd:element>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="EmailMessageDefinition">
<xsd:sequence>
<xsd:element name="To" minOccurs="0"
type="tns:EmailRecipient" maxOccurs="unbounded"></xsd:element>
<xsd:element name="From"
type="tns:EmailAddress"></xsd:element>
<xsd:element name="Subject"
type="xsd:normalizedString"></xsd:element>
...
</xsd:sequence>
<xsd:attribute name="ID" type="xsd:string" use="required"/>
</xsd:complexType>
The noticeable thing is that the EmailMessageDefinition element has an
attribute called ID and that it should be namespace qualified
(attributeFormDefault="qualified" ).
Using CXF as a SOAP processor works correctly for everything I've tried
with it so far, my problem comes when I try to marshall an
EmailMessageDefinition manually:
EmailMessageDefinition defn = createMessageDefinition( "id",
"payload" ); // returns an EmailMessageDefinition with the id set to
"id" and some standard recipients
try
{
JAXBDataBinding binding = new JAXBDataBinding();
JAXBContext jc = JAXBContext.newInstance(
"com.groupgti.esb.jobengines.email.service.groupgtisupportsystem.emailschedulertarget"
);
Marshaller marshaller = jc.createMarshaller();
StringWriter writer = new StringWriter();
marshaller.marshal( new JAXBElement( new QName(
"http://groupgti.com/esb/jobengines/email/service/GroupGtiSupportSystem/EmailSchedulerTarget",
"EmailMessageDefinition" ), EmailMessageDefinition.class, defn ), writer );
System.out.println( writer.toString() );
That gives:
<?xml version="1.0" encoding="UTF-8"
standalone="yes"?><ns1:EmailMessageDefinition ns1:ID="id"
xmlns:ns1="http://groupgti.com/esb/jobengines/email/service/GroupGtiSupportSystem/EmailSchedulerTarget">...</ns1:EmailMessageDefinition>
Which is correct, but the namespace is repeated all over the place and
is ugly.
So I try to make it the default namespace by adding:
private class NamespaceMapper extends NamespacePrefixMapper
{
@Override
public String getPreferredPrefix( String namespaceUri, String
suggestion, boolean requirePrefix )
{
if(
"http://groupgti.com/esb/jobengines/email/service/GroupGtiSupportSystem/EmailSchedulerTarget".equals(
namespaceUri ) )
{
return "";
}
else
{
return suggestion;
}
}
}
And this is the result:
<?xml version="1.0" encoding="UTF-8"
standalone="yes"?><EmailMessageDefinition ID="id"
xmlns="http://groupgti.com/esb/jobengines/email/service/GroupGtiSupportSystem/EmailSchedulerTarget">...</EmailMessageDefinition>
That result is wrong, according to the schema, because the attribute is
not affected by the default namespace.
This can be demonstrated by unmarshalling the result, which fails to set
the ID on the resulting object.
I tried adding:
@Override
public String[] getPreDeclaredNamespaceUris2()
{
String[] result = { "ns",
"http://groupgti.com/esb/jobengines/email/service/GroupGtiSupportSystem/EmailSchedulerTarget"
};
return result;
}
but that didn't help:
<?xml version="1.0" encoding="UTF-8"
standalone="yes"?><ns:EmailMessageDefinition ID="id"
xmlns="http://groupgti.com/esb/jobengines/email/service/GroupGtiSupportSystem/EmailSchedulerTarget"
xmlns:ns="http://groupgti.com/esb/jobengines/email/service/GroupGtiSupportSystem/EmailSchedulerTarget">...</ns:EmailMessageDefinition>
I think the marshaller needs special handling for qualified attributes
with an enforced default namespace.
1. Please can you confirm that this is a bug and not my incompetence (if
you'd like me to file it please point me in the right direction).
2. Do you know a workaround that will put the elements in the default
namespace? If not, the workaround is to namespace everything, which is
done correctly.
Thanks
Jim