Exception in thread "main" javax.xml.bind.PropertyException: name: eclipselink.media-type value: ...

Learn exception in thread "main" javax.xml.bind.propertyexception: name: eclipselink.media-type value: application/json with practical examples, diagrams, and best practices. Covers java, json, jax...

Resolving javax.xml.bind.PropertyException: eclipselink.media-type with JAXB and JSON

Hero image for Exception in thread "main" javax.xml.bind.PropertyException: name: eclipselink.media-type value: ...

Understand and fix the 'javax.xml.bind.PropertyException: name: eclipselink.media-type value: application/json' error when using JAXB with EclipseLink MOXy for JSON binding.

The javax.xml.bind.PropertyException: name: eclipselink.media-type value: application/json error typically arises when you're trying to leverage JAXB (Java Architecture for XML Binding) with EclipseLink MOXy as your JAXB provider to handle JSON serialization/deserialization, but the MOXy-specific property eclipselink.media-type is either incorrectly set or not recognized in the context of your JAXB operations. This article will guide you through understanding the root causes and providing effective solutions to resolve this common issue.

JAXB is a standard Java API for mapping Java objects to XML and vice versa. While its primary focus is XML, providers like EclipseLink MOXy extend its capabilities to handle other data formats, most notably JSON. MOXy achieves this by introducing its own set of properties and configurations that allow JAXB contexts to understand and process JSON structures.

The eclipselink.media-type property is crucial for MOXy to know what kind of output format to produce or expect when marshalling (Java to data) or unmarshalling (data to Java). When set to application/json, it instructs MOXy to treat the data as JSON. The PropertyException indicates that the JAXB runtime, for some reason, failed to properly interpret or apply this property.

flowchart TD
    A[Start JAXB Context] --> B{Is MOXy JAXB Provider Configured?}
    B -- No --> C[Default JAXB Provider (XML Only)]
    B -- Yes --> D{Set 'eclipselink.media-type' Property?}
    D -- No --> E[MOXy Defaults to XML]
    D -- Yes --> F{Property Value Valid?}
    F -- No --> G["javax.xml.bind.PropertyException: eclipselink.media-type"]
    F -- Yes --> H[MOXy Processes JSON Successfully]
    C --> I[Error: Cannot Process JSON]
    E --> I

Flowchart illustrating the JAXB context initialization and MOXy property handling.

Common Causes and Solutions

This exception typically points to one of two main problems: either MOXy isn't correctly configured as the JAXB provider, or the property is being set incorrectly during the JAXBContext creation or marshaller/unmarshaller configuration.

Solution 1: Ensuring MOXy is the JAXB Provider

The most common reason for this error is that the JVM is not picking up EclipseLink MOXy as the JAXB provider. JAXB uses a discovery mechanism to find its provider. You can explicitly tell JAXB to use MOXy by creating a jaxb.properties file in the same package as your JAXB-annotated classes.

javax.xml.bind.JAXBContextFactory=org.eclipse.persistence.jaxb.JAXBContextFactory

Alternatively, you can set the javax.xml.bind.JAXBContextFactory system property at runtime, though the jaxb.properties file is generally preferred for clarity and portability.

Solution 2: Correctly Setting the Media Type Property

Once MOXy is confirmed as the provider, you need to correctly set the eclipselink.media-type property. This is typically done when creating the JAXBContext or when configuring the Marshaller or Unmarshaller.

1. Create JAXBContext with MOXy properties

When creating the JAXBContext, you can pass a map of properties. This is the recommended way to configure MOXy for JSON.

2. Configure Marshaller/Unmarshaller

After creating the context, you can set the media type directly on the Marshaller or Unmarshaller instances. This is useful if you need to switch between XML and JSON output with the same JAXBContext.

import org.eclipse.persistence.jaxb.JAXBContextProperties;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.Marshaller;
import javax.xml.bind.Unmarshaller;
import java.io.StringWriter;
import java.util.HashMap;
import java.util.Map;

public class JsonMarshallerExample {

    // Your JAXB-annotated class
    public static class MyObject {
        public String name;
        public int value;

        public MyObject() {}
        public MyObject(String name, int value) {
            this.name = name;
            this.value = value;
        }
    }

    public static void main(String[] args) throws Exception {
        // 1. Create JAXBContext with MOXy properties
        Map<String, Object> properties = new HashMap<>();
        properties.put(JAXBContextProperties.MEDIA_TYPE, "application/json");
        properties.put(JAXBContextProperties.JSON_INCLUDE_ROOT, false); // Optional: for root element suppression

        JAXBContext jaxbContext = JAXBContext.newInstance(new Class[]{MyObject.class}, properties);

        // 2. Create Marshaller
        Marshaller marshaller = jaxbContext.createMarshaller();
        marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);

        // The media type is already set via JAXBContextProperties, but can also be set here:
        // marshaller.setProperty(JAXBContextProperties.MEDIA_TYPE, "application/json");

        // 3. Marshal object to JSON
        MyObject obj = new MyObject("example", 123);
        StringWriter writer = new StringWriter();
        marshaller.marshal(obj, writer);
        System.out.println("Marshalled JSON:\n" + writer.toString());

        // 4. Create Unmarshaller
        Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();
        // The media type is already set via JAXBContextProperties, but can also be set here:
        // unmarshaller.setProperty(JAXBContextProperties.MEDIA_TYPE, "application/json");

        // 5. Unmarshal JSON to object
        String jsonInput = "{\"name\":\"unmarshalled\", \"value\":456}";
        MyObject unmarshalledObj = (MyObject) unmarshaller.unmarshal(new java.io.StringReader(jsonInput));
        System.out.println("\nUnmarshalled Object: " + unmarshalledObj.name + ", " + unmarshalledObj.value);
    }
}

Maven/Gradle Dependencies

To use EclipseLink MOXy, you need to include the necessary dependencies in your project's build file. For Maven, this typically involves adding the eclipselink dependency.

Maven (pom.xml)

org.eclipse.persistence eclipselink 2.7.10 jakarta.xml.bind jakarta.xml.bind-api 2.3.3

Gradle (build.gradle)

implementation 'org.eclipse.persistence:eclipselink:2.7.10' // Use a recent stable version implementation 'jakarta.xml.bind:jakarta.xml.bind-api:2.3.3' // Or compatible JAXB API version

By following these steps and ensuring proper configuration, you should be able to resolve the javax.xml.bind.PropertyException: eclipselink.media-type error and successfully use EclipseLink MOXy for JSON binding with JAXB.