How to serialize my SOAP request class with namespaces using XmlMapper?

306 Views Asked by At

For a SOAP API I need to POST a request XML in the following format:

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ws1="http://ws1.myapi.ch/">
  <soapenv:Header/>
  <soapenv:Body>
    <ws1:Suchen>
      <ws1:Benutzername>test</ws1:Benutzername>
      <ws1:Passwort>test</ws1:Passwort>
      <ws1:Sprache>De</ws1:Sprache>
      <ws1:Datenname>Arten</ws1:Datenname>
      <ws1:Einstellungen></ws1:Einstellungen>
    </ws1:Suchen>
  </soapenv:Body>
</soapenv:Envelope>

In my Java code I have the following POJO for this:

@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "", propOrder = {
    "benutzername",
    "passwort",
    "sprache",
    "datenname",
    "suchwerte",
    "einstellungen"
})
@XmlRootElement(name = "Suchen")
public class Suchen {

    @XmlElement(name = "Benutzername")
    protected String benutzername;
    @XmlElement(name = "Passwort")
    protected String passwort;
    @XmlElement(name = "Sprache")
    protected String sprache;
    @XmlElement(name = "Datenname")
    protected String datenname;
    @XmlElement(name = "Suchwerte")
    protected String suchwerte;
    @XmlElement(name = "Einstellungen")
    protected String einstellungen;

    /**
     * Gets the value of the benutzername property.
     *
     * @return possible object is {@link String }
     */
    public String getBenutzername() {
        return benutzername;
    }

    /**
     * Sets the value of the benutzername property.
     *
     * @param value allowed object is {@link String }
     */
    public void setBenutzername(String value) {
        this.benutzername = value;
    }

    /**
     * Gets the value of the passwort property.
     *
     * @return possible object is {@link String }
     */
    public String getPasswort() {
        return passwort;
    }

    /**
     * Sets the value of the passwort property.
     *
     * @param value allowed object is {@link String }
     */
    public void setPasswort(String value) {
        this.passwort = value;
    }

    /**
     * Gets the value of the sprache property.
     *
     * @return possible object is {@link String }
     */
    public String getSprache() {
        return sprache;
    }

    /**
     * Sets the value of the sprache property.
     *
     * @param value allowed object is {@link String }
     */
    public void setSprache(String value) {
        this.sprache = value;
    }

    /**
     * Gets the value of the datenname property.
     *
     * @return possible object is {@link String }
     */
    public String getDatenname() {
        return datenname;
    }

    /**
     * Sets the value of the datenname property.
     *
     * @param value allowed object is {@link String }
     */
    public void setDatenname(String value) {
        this.datenname = value;
    }

    /**
     * Gets the value of the suchwerte property.
     *
     * @return possible object is {@link String }
     */
    public String getSuchwerte() {
        return suchwerte;
    }

    /**
     * Sets the value of the suchwerte property.
     *
     * @param value allowed object is {@link String }
     */
    public void setSuchwerte(String value) {
        this.suchwerte = value;
    }

    /**
     * Gets the value of the einstellungen property.
     *
     * @return possible object is {@link String }
     */
    public String getEinstellungen() {
        return einstellungen;
    }

    /**
     * Sets the value of the einstellungen property.
     *
     * @param value allowed object is {@link String }
     */
    public void setEinstellungen(String value) {
        this.einstellungen = value;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) {
            return true;
        }
        if (o == null || getClass() != o.getClass()) {
            return false;
        }
        Suchen suchen = (Suchen) o;
        return Objects.equals(benutzername, suchen.benutzername) && Objects.equals(passwort, suchen.passwort) && Objects.equals(sprache, suchen.sprache)
                && Objects.equals(datenname, suchen.datenname) && Objects.equals(suchwerte, suchen.suchwerte) && Objects.equals(einstellungen,
                suchen.einstellungen);
    }

    @Override
    public int hashCode() {
        return Objects.hash(benutzername, passwort, sprache, datenname, suchwerte, einstellungen);
    }
}
final String requestData = xmlMapper.writeValueAsString(requestPojo);

requestData looks like this:

<Suchen>
  <benutzername>test</benutzername>
  <passwort>test</passwort>
  <sprache>De</sprache>
  <datenname>Arten</datenname>
  <suchwerte/>
  <einstellungen/>
</Suchen>

Which does not meet the requirements at all.

So how can I add those special namespaces xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ws1="http://ws1.myapi.ch/?

What is the best way to add those element name prefixes like <ws1:Suchen>?

1

There are 1 best solutions below

0
On

In order to serialize your Suchen class with namespaces using XmlMapper, you need to use the @XmlSchema, @XmlNs, and @XmlElement annotations from the javax.xml.bind.annotation package to specify the namespace and prefix information.

Below is the step-by-step guide to achieve the desired XML output with namespaces:

1. Define the Namespace and Prefix

Use the @XmlSchema and @XmlNs annotations on your package to define the namespace and prefix. Create a file named package-info.java in the same package as your Suchen class:

@XmlSchema(
    xmlns = {
        @XmlNs(prefix = "ws1", namespaceURI = "http://ws1.myapi.ch/")
    },
    elementFormDefault = XmlNsForm.QUALIFIED
)
package your.package.name;

import javax.xml.bind.annotation.XmlNs;
import javax.xml.bind.annotation.XmlNsForm;
import javax.xml.bind.annotation.XmlSchema;
  1. Annotate Your Class and Fields: Annotate your Suchen class and its fields with the @XmlElement annotation, specifying the namespace and name.

       @XmlRootElement(name = "Suchen", namespace = "http://ws1.myapi.ch/")
       public class Suchen {
           @XmlElement(name = "Benutzername", namespace = "http://ws1.myapi.ch/")
           protected String benutzername;
           // ... other fields with similar annotations
       }

  1. Serialize the Object: Use XmlMapper to serialize the Suchen object, which should now include the namespace and prefix information.

    
    
     XmlMapper xmlMapper = new XmlMapper();
        String requestData = xmlMapper.writeValueAsString(new Suchen());
    
    

  1. Add Envelope and Body Manually Since XmlMapper will only serialize the Suchen object, you may need to manually add the soapenv:Envelope and soapenv:Body elements to the XML string, or create corresponding classes for them and serialize the entire envelope object.

    Full Example: Here's a full example, assuming you have added the package-info.java as mentioned:

    
    
      @XmlAccessorType(XmlAccessType.FIELD)
        @XmlType(name = "", propOrder = {
            "benutzername",
            "passwort",
            "sprache",
            "datenname",
            "einstellungen"
        })
        @XmlRootElement(name = "Suchen", namespace = "http://ws1.myapi.ch/")
        public class Suchen {
            @XmlElement(name = "Benutzername", namespace = "http://ws1.myapi.ch/")
            protected String benutzername;
            // ... other fields and methods with similar annotations
        }
    
    

By following these steps, you should be able to generate the desired XML output with the correct namespace and prefix information.