Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to prevent JAXB from writing unused namespaces during marshalling

Has someone ever been able to remove unused namespaces during marshal of an object using JAXB? Here is a link of the requested feature: https://github.com/javaee/jaxb-v2/issues/103 (see description)

Is there a property for configuring JAXB for this? Has this been fixed in MOXy?

I am currently traversing the object that needs to be marshalled and extract all classes that need to be bound into Class[] classesToBeBound. Then I create a new JAXBContext.newInstance(classesToBeBound)

The unused namespaces now are not included in the XML.

I know that xml validation is valid even with the unused namespaces but to me this is something a framework should handle.

The following link https://blogs.oracle.com/enterprisetechtips/entry/customizing_jaxb mentions various fixed (see middle of the text somewhere) but when trying to find the solution in those links either the link is broken or no-one really solved it.

Any comments are welcome.

(EDIT) Plain text:

GIVEN

a new instance of JAXBContext and add 2 classes with each a separate namespace. 

WHEN

marshalling a class that has these 2 classes as a property but only 1 of them is not null 

THEN

I expect only the namespace of the property that is not null to be visible in the XML. 

BUT the ACTUAL is

that both namespaces are in the xml. 

So my question was how can I remove or tell JAXB to NOT write the unused namespaces?

To put it in java-code: GIVEN

public class Foo{
  private Bar bar; //namespace something2
  private User user; //namespace user
}

WHEN

JAXBContext c = JAXBContext.newInstance(Foo.class, Bar.class, User.class);
...
Foo foo = new Foo();
foo.setBar(null);
foo.setUser(new User("Bob"));
marshaller.umarshal(foo);

THEN I expect the xml to be

<foo xmlns="something1"  xmlns:user="user">
  <user:name>Bob</user:name>
</foo>

BUT the ACTUAL is (note the something2 namespace)

<foo xmlns="something1" xmlns:user="user" xmlns:bar="something2">
  <user:name>Bob</user:name>
</foo>

Of course this is a simplified example and our specification of a type has around 30 different namespaces.

like image 525
TimothyBrake Avatar asked Apr 08 '14 15:04

TimothyBrake


People also ask

How do I become a marshal without a namespace?

setDefaultNamespace("") solved the issue. One more thing you have to care in order to remove the namespace prefix from the output is that everywhere you have @XmlElement ensure it does not include the namespace property like @XmlElement(name="", namespace"http://...") ; otherwise, none of solutions will work.

How does JAXB marshalling work?

In JAXB, marshalling involves parsing an XML content object tree and writing out an XML document that is an accurate representation of the original XML document, and is valid with respect the source schema. JAXB can marshal XML data to XML documents, SAX content handlers, and DOM nodes.

Is JAXB context thread safe?

JAXBContext is thread safe and should only be created once and reused to avoid the cost of initializing the metadata multiple times. Marshaller and Unmarshaller are not thread safe, but are lightweight to create and could be created per operation.


1 Answers

As far as I know, this is indeed not possible in JAXB - and is actually a well-known issue. As you have noticed it, the list of produced namespaces are the ones that have been registered in your JAXBContext, and not the ones that are effectively used when marshalling :-(

I the past, I used the same workaround as you (identify the various used classes and narrow the JAXBContext to this limited set of classes).

Another typical workaround is a 2-step processing: a first marshalling with JAXB, followed by a XSLT transformation to get rid of let's says "polluting" namespaces.

like image 168
TacheDeChoco Avatar answered Oct 27 '22 00:10

TacheDeChoco