Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Custom namespace marshalling using JAXB Glassfish results in property "org.glassfish.jaxb.runtime.marshaller.NamespacePrefixMapper" is not supported #306

Closed
Aravinda93 opened this issue Mar 8, 2024 · 2 comments

Comments

@Aravinda93
Copy link

I am using the Jakarta/Glassfish to marshall the Java objects into XML but during the marshalling I need to provide some of the custom namespaces to my Marshaller and JAXBContext. I referred the documentation and answer here to do the same but its resulting in the error:

Exception in thread "main" jakarta.xml.bind.JAXBException: property "org.glassfish.jaxb.runtime.marshaller.NamespacePrefixMapper" is not supported
	at org.glassfish.jaxb.runtime.v2.ContextFactory.createContext(ContextFactory.java:126)
	at org.glassfish.jaxb.runtime.v2.ContextFactory.createContext(ContextFactory.java:246)
	at org.glassfish.jaxb.runtime.v2.JAXBContextFactory.createContext(JAXBContextFactory.java:58)
	at jakarta.xml.bind.ContextFinder.find(ContextFinder.java:324)
	at jakarta.xml.bind.JAXBContext.newInstance(JAXBContext.java:392)
	at io.test.convert.MainXML.main(MainXML.java:27)

Following is the completed code I have:
Child1.class:

package io.test.convert;

import jakarta.xml.bind.annotation.XmlAccessType;
import jakarta.xml.bind.annotation.XmlAccessorType;
import jakarta.xml.bind.annotation.XmlRootElement;
import jakarta.xml.bind.annotation.XmlType;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
import lombok.ToString;

@XmlRootElement(name = "Child1")
@XmlType(
        name = "Child1",
        propOrder = {
                "name",
                "age",
                "originalName"
        },
        factoryClass = ObjectFactory.class,
        factoryMethod = "createChild1")
@Data
@NoArgsConstructor
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
@XmlAccessorType(XmlAccessType.FIELD)
public class Child1 extends Parent {
    private String originalName;
}

Parent.class:

package io.test.convert;

import com.fasterxml.jackson.annotation.JsonIgnore;
import jakarta.xml.bind.annotation.XmlAccessType;
import jakarta.xml.bind.annotation.XmlAccessorType;
import jakarta.xml.bind.annotation.XmlTransient;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.io.Serializable;

@Data
@NoArgsConstructor
@AllArgsConstructor
@XmlAccessorType(XmlAccessType.FIELD)
@XmlTransient
@Builder
public class Parent  implements Serializable  {
    @XmlTransient
    @JsonIgnore
    private String type;
    private String name;
    private String age;
}

CustomNamespacePrefixMapper.class:

package io.test.convert;

import org.glassfish.jaxb.runtime.marshaller.NamespacePrefixMapper;
import java.util.HashMap;
import java.util.Map;

public class CustomNamespacePrefixMapper extends NamespacePrefixMapper {

    public static final Map<String, String> NAMESPACE_MAP = Map.of(
            "http://www.w3.org/2001/XMLSchema-instance", "xsi",
            "https://example1.com/", "example1",
            "https://example2.com/", "example2");

    private Map<String, String> namespaceMap;

    public CustomNamespacePrefixMapper(final Map<String, String> namespaceMap) {
        this.namespaceMap = namespaceMap;
    }
    public CustomNamespacePrefixMapper() {
        this(new HashMap<>(NAMESPACE_MAP));
    }

    @Override
    public String getPreferredPrefix(String namespaceUri, String suggestion, boolean requirePrefix) {
        return namespaceMap.getOrDefault(namespaceUri, suggestion);
    }
}

MainXML.class:

package io.test.convert;

import jakarta.xml.bind.JAXBContext;
import jakarta.xml.bind.Marshaller;
import jakarta.xml.bind.UnmarshalException;
import jakarta.xml.bind.Unmarshaller;

import javax.xml.stream.XMLInputFactory;
import javax.xml.stream.XMLStreamReader;
import java.io.InputStream;
import java.util.HashMap;
import java.util.Map;

public class MainXML {
    public static void main(String[] args) throws Exception {
        final Map<String, String> myNamespaces = new HashMap<>();
        myNamespaces.put("test", "https://test.com");
        myNamespaces.put("test2", "https://test2.com");

        final InputStream xmlInputStream = Main.class.getResourceAsStream("/SampleXML.xml");

        final XMLInputFactory inputFactory = XMLInputFactory.newInstance();
        inputFactory.setProperty(XMLInputFactory.SUPPORT_DTD, Boolean.FALSE);
        inputFactory.setProperty(XMLInputFactory.IS_SUPPORTING_EXTERNAL_ENTITIES, Boolean.FALSE);
        final XMLStreamReader xmlStreamReader = inputFactory.createXMLStreamReader(xmlInputStream);

        final JAXBContext jaxbContext = JAXBContext.newInstance("io.test.convert", Thread.currentThread().getContextClassLoader(),
                new HashMap<>() {
                    {
                        put(
                                "org.glassfish.jaxb.runtime.marshaller.NamespacePrefixMapper",
                                new CustomNamespacePrefixMapper());
                    }
                });
        //final JAXBContext jaxbContext = JAXBContext.newInstance("io.test.convert", Thread.currentThread().getContextClassLoader());
        final Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();
        xmlStreamReader.next();

        final Marshaller marshaller = jaxbContext.createMarshaller();
        marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
        marshaller.setProperty(Marshaller.JAXB_FRAGMENT, Boolean.TRUE);
        marshaller.setProperty("org.glassfish.jaxb.runtime.marshaller.NamespacePrefixMapper", new CustomNamespacePrefixMapper());

        try {
            while (xmlStreamReader.hasNext()) {
                Object event = unmarshaller.unmarshal(xmlStreamReader, Child1.class).getValue();
                if (event instanceof Child1) {
                    Child1 child1 = (Child1) event;
                    marshaller.marshal(child1, System.out);
                }
            }
        } catch (UnmarshalException e) {
            // Handle any unmarshalling exceptions
            e.printStackTrace();
        }
    }
}

Following is my sampleXML.xml:

<Child1>
    <type>ChildType</type>
    <name>Batman</name>
    <age>30</age>
    <originalName>Bruce</originalName>
</Child1>

When I run I get the error:

Exception in thread "main" jakarta.xml.bind.JAXBException: property "org.glassfish.jaxb.runtime.marshaller.NamespacePrefixMapper" is not supported
	

How to provide the custom namespaces to the JAXBContext/Marshaller so it can be used during the marshalling of the Java objects to XML?

Following are my dependencies:

  <dependencies>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.30</version>
        </dependency>

        <dependency>
            <groupId>org.glassfish.jaxb</groupId>
            <artifactId>jaxb-runtime</artifactId>
            <version>4.0.1</version>
        </dependency>

        <dependency>
            <groupId>org.glassfish.jaxb</groupId>
            <artifactId>jaxb-core</artifactId>
            <version>4.0.1</version>
        </dependency>

        <dependency>
            <groupId>jakarta.xml.bind</groupId>
            <artifactId>jakarta.xml.bind-api</artifactId>
            <version>4.0.1</version>
        </dependency>
    </dependencies>
@lukasj
Copy link
Contributor

lukasj commented Mar 8, 2024

this is a project for jakarta.xml.bind-api, the problem you seem to have is related to jaxb-runtime. The best would be to file issue there, in the runtime project's tracker and that is at https://github.com/eclipse-ee4j/jaxb-ri/issues

@lukasj lukasj closed this as completed Mar 8, 2024
@lukasj lukasj closed this as not planned Won't fix, can't repro, duplicate, stale Mar 8, 2024
@Aravinda93
Copy link
Author

@lukasj Thanks for the guidence and sorry for posting the in the wrong repo.
As informed I have posted in the correct repo now, can you please have a look and provide some response?
eclipse-ee4j/jaxb-ri#1795

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants