3

I have a situation where I need to setup my namespaces dynamically for my jaxb classes. my namespace in jaxb classes have a version that needs to be dynamically changed.

 @XmlRootElement(name = "myobject",namespace="http://myhost.com/version-2")
 @XmlAccessorType(XmlAccessType.FIELD)
 @XmlType
 public class myObject{

 }

my marshalling works perfect when I use this static namespacing mechanism, but in my real situation, I need this version to be changed dynamically..

I tried this approach to solve this issue when marshalling

 XMLStreamWriter xmlStreamWriter =     
 XMLOutputFactory.newInstance().createXMLStreamWriter(stringWriter);
 String uri = "http://myhost.com/ver-"+version;

//xmlStreamWriter.setDefaultNamespace(uri);
xmlStreamWriter.writeStartDocument("1.0");

xmlStreamWriter.writeNamespace("ns1", uri);

my attempt to use setDefaultNamespace was not successful and writeNamespace throw me an error Invalid state: start tag is not opened at writeNamespace

any input on how this can be resolved is highly appreciated.

Sanath
  • 4,774
  • 10
  • 51
  • 81
  • Have a look at http://stackoverflow.com/questions/277502/jaxb-how-to-ignore-namespace-during-unmarshalling-xml-document There are several examples on how to manipulate payload on the fly. – andbi Mar 25 '12 at 06:16

2 Answers2

2

You may implement a XMLStreamWriter that delegates all calls to the original writer, but overrides the writeNamespace(...) method:

public void writeNamespace(String prefix, String uri) {
  if ("http://myhost.com/version-2".equals(uri) {
    uri = "http://myhost.com/version-" + version;
  }
  delegate.writeNamespace(prefix, uri);
}
chris
  • 3,573
  • 22
  • 20
  • when I try to override this.. xmlStreamWriter.writeNamespace("ns2", http://myhost.com /version-2); I get this error .. Invalid state: start tag is not opened at writeNamespace(ns2, http://myhost.com/version-2) – Sanath Mar 25 '12 at 22:11
  • Please try to override the startElement(String uri,...) and setPrefix(...) metods in the same manner. Basically, every method getting a namespaceURI parameter needs to do the namespace transformation. – chris Mar 26 '12 at 18:31
  • since I only wanted to add the name space version only in the root element of the xml, I did this trick.. I had the xml annotated model class like this @XmlRootElement(name = "myobject",namespace="myhost.com /version-") @XmlAccessorType(XmlAccessType.FIELD) @XmlType public class myObject{ } – Sanath Apr 09 '12 at 04:51
  • where version was supplied like version- and just before passing the xml to be marshalled, I added the version number to the xml string programatically. if(version == 1){ String ns = "myhost.com/version-"+version; } the issue is how to address this problem when unmarshalling? – Sanath Apr 09 '12 at 04:51
1

Did you consider using an XSL-T transformation ? Depending on your schema, it could be relatively straight-forward to replace the namespace after marshalling.

Patrice M.
  • 4,209
  • 2
  • 27
  • 36
  • how about the performance of this ..I feel that the performance of reading the dom tree again after marshalling will impact on performance. why can't I use default namespacing or something like that when creating the xml stream writer? – Sanath Mar 25 '12 at 04:33
  • 1
    I guess I remember that there exist streaming XSL processors. They have limited functionality, but for such simple tasks it should be ok. – Jarekczek Jun 02 '17 at 13:01