SEVERE: MessageBodyWriter not found for media type=application/xml
Asked Answered
R

8

8

I know this may sound like a duplicate of this or some others, but bear with me.

I have a very basic JAX-RS resource, have added all the required annotations that I saw in this tutorial I followed here.
But I keep getting HTTP Status 500 and the following log output in Eclipse's console.

Mar 18, 2021 1:35:23 AM org.glassfish.jersey.message.internal.WriterInterceptorExecutor$TerminalWriterInterceptor aroundWriteTo
SEVERE: MessageBodyWriter not found for media type=application/xml, type=class com.varun.demorest.model.User, genericType=class com.varun.demorest.model.User.

Using Maven, but even after adding most suggestions I am finding on similar questions, I see that it was all mostly already included under

<groupId>org.glassfish.jersey</groupId>
<artifactId>jersey-bom</artifactId>

pom.xml:

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">

    <modelVersion>4.0.0</modelVersion>

    <groupId>com.varun</groupId>
    <artifactId>demorest</artifactId>
    <packaging>war</packaging>
    <version>0.0.1-SNAPSHOT</version>
    <name>demorest</name>

    <build>
        <finalName>demorest</finalName>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>2.5.1</version>
                <inherited>true</inherited>
                <configuration>
                    <source>1.7</source>
                    <target>1.7</target>
                </configuration>
            </plugin>
        </plugins>
    </build>

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.glassfish.jersey</groupId>
                <artifactId>jersey-bom</artifactId>
                <version>${jersey.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

    <dependencies>
        <dependency>
            <groupId>org.glassfish.jersey.containers</groupId>
            <artifactId>jersey-container-servlet-core</artifactId>
            <!-- use the following artifactId if you don't need servlet 2.x compatibility -->
            <!-- artifactId>jersey-container-servlet</artifactId -->
        </dependency>
        <dependency>
            <groupId>org.glassfish.jersey.inject</groupId>
            <artifactId>jersey-hk2</artifactId>
        </dependency>
        
        <dependency>
            <groupId>org.glassfish.jersey.media</groupId>
            <artifactId>jersey-media-moxy</artifactId>
        </dependency>
                
        <!-- https://mvnrepository.com/artifact/jakarta.xml.bind/jakarta.xml.bind-api -->
        <dependency>
            <groupId>jakarta.xml.bind</groupId>
            <artifactId>jakarta.xml.bind-api</artifactId>
            <version>3.0.0</version>
        </dependency>
                
        <!-- https://mvnrepository.com/artifact/javax.servlet/javax.servlet-api -->
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
            <version>4.0.1</version>
            <scope>provided</scope>
        </dependency>   
    </dependencies>
    <properties>
        <jersey.version>3.0.1</jersey.version>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>
</project>

My Model class:
User.java:

package com.varun.demorest.model;

import jakarta.xml.bind.annotation.XmlRootElement;

@XmlRootElement
public class User {
    private String name;
    private String phone;
    
    public User() {
    }
    
    public void setName(String name) {
        this.name = name;
    }

    public void setPhone(String phone) {
        this.phone = phone;
    }

    public String getName() {
        return name;
    }
    public String getPhone() {
        return phone;
    }
}

CustomResource.java:

package com.varun.demorest;

import com.varun.demorest.model.User;

import jakarta.ws.rs.GET;
import jakarta.ws.rs.Path;
import jakarta.ws.rs.Produces;
import jakarta.ws.rs.core.MediaType;

@Path("getUser")
public class CustomResource {
    
    @GET
    @Produces(MediaType.APPLICATION_XML)
    public User getUser() {
        
        System.out.println("getUser Called!");
        User user = new User();
        user.setName("Varun");
        user.setPhone("xxxxxxxxxx");
        System.out.println(user);
        return user;
    }
}

I am unexperienced in JAX-RS, so any help is much appreciated.
Using Java 11 and Tomcat 10.

Rubdown answered 17/3, 2021 at 20:14 Comment(6)
Can you try to use javax.xml.bind.annotation.XmlRootElement and see what happens.Volatile
@PaulSamsotha That's actually what I had tried first. But javax.xml.bind.annotation.XmlRootElement has been depreacated and discarded for a good while. The binds were moved to jakarta.xml.bind.annotation.XmlRootElementRubdown
Everything looks good. Maybe try to change the maven-compiler to use Java 11. You say you're using Java 11, but the Maven configuration shows you're using Java 7.Volatile
@PaulSamsotha I changed the <source> and <target> values inside the build configuration in the pom.xml from 1.7 to 11. Unfortunately, no change.Rubdown
Try thisVolatile
You can try to add Jersey-media-jaxb but I’m pretty sure it’s already pulled in as a transitive dependency.Volatile
O
6

as say @Paul Samsotha, it solve this problem for me, I append in pom.xml this:

<dependency>
    <groupId>org.glassfish.jersey.media</groupId>
    <artifactId>jersey-media-jaxb</artifactId>
    <version>3.0.2</version>
</dependency>

and it fix problem.

Orgeat answered 6/6, 2021 at 17:37 Comment(1)
I'm still on version 2 (2.39 right now) of Jersey, but also here XML stopped working at some point. Adding jersey-media-jaxb as dependency solved the problem. I checked before, and it was not pulled in as transitive dependency.Spanker
O
3

I was following the same tutorial and having the same issue, I fixed it by adding the following dependencies:

`       <dependency>
            <groupId>jakarta.xml.bind</groupId>
            <artifactId>jakarta.xml.bind-api</artifactId>
            <version>3.0.0</version>
        </dependency>
        <dependency>
            <groupId>com.sun.xml.bind</groupId>
            <artifactId>jaxb-impl</artifactId>
            <version>3.0.0</version>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>org.glassfish.jersey.media</groupId>
            <artifactId>jersey-media-jaxb</artifactId>
            <version>3.0.2</version>
        </dependency>
` 
Obstruct answered 16/12, 2021 at 5:29 Comment(0)
M
3

I am on JDK 17 and Tomcat 10, faced the same issue. Adding the following dependencies worked for me to enable JAXB without any error. (If you don't have any of these - some or the other error would come)

<dependency>
    <groupId>jakarta.xml.bind</groupId>
    <artifactId>jakarta.xml.bind-api</artifactId>
    <version>4.0.0</version>
</dependency>

<dependency>
    <groupId>com.sun.xml.bind</groupId>
    <artifactId>jaxb-impl</artifactId>
    <version>4.0.1</version>
</dependency>
<dependency>
    <groupId>org.glassfish.jaxb</groupId>
    <artifactId>jaxb-runtime</artifactId>
    <version>4.0.1</version>
</dependency>
<dependency>
    <groupId>org.glassfish.jersey.media</groupId>
    <artifactId>jersey-media-jaxb</artifactId>
    <version>3.0.2</version>
</dependency>
<dependency>
    <groupId>jakarta.activation</groupId>
    <artifactId>jakarta.activation-api</artifactId>
    <version>2.1.0</version>
</dependency>
Macrobiotics answered 10/12, 2022 at 7:38 Comment(0)
T
2

was running a similar code in Eclipse 2022-03, ran into same error fixed it with these three dependencies

<dependency>
        <groupId>jakarta.xml.bind</groupId>
        <artifactId>jakarta.xml.bind-api</artifactId>
        <version>3.0.0</version>
    </dependency>
    <dependency>
        <groupId>com.sun.xml.bind</groupId>
        <artifactId>jaxb-impl</artifactId>
        <version>3.0.0</version>
        <scope>runtime</scope>
    </dependency>
    <dependency>
        <groupId>org.glassfish.jersey.media</groupId>
        <artifactId>jersey-media-jaxb</artifactId>
        <version>3.0.2</version>
    </dependency>

all before I was able to return Xml data, I wonder why these works

Trio answered 15/5, 2022 at 16:36 Comment(1)
This is a duplicate of this other answerCurvaceous
D
1

I have used the jaxb-runtime and jersey-media-jaxb jars which fixed the error.

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

<dependency>
    <groupId>org.glassfish.jersey.media</groupId>
    <artifactId>jersey-media-jaxb</artifactId>
    <version>3.0.4</version>
</dependency>
Dialyze answered 15/4, 2022 at 18:37 Comment(0)
U
1

added @jakarta.xml.bind.annotation.XmlRootElement in pojo class. and in pom.xml added below dependencies

 <dependency>
    <groupId>org.glassfish.jersey.media</groupId>
    <artifactId>jersey-media-jaxb</artifactId>
    <version>3.0.4</version>
</dependency>
<dependency>
    <groupId>org.glassfish.jaxb</groupId>
    <artifactId>jaxb-runtime</artifactId>
    <version>4.0.0-M4</version>
</dependency>

this resolved issue.

Unquestionable answered 10/5, 2022 at 15:33 Comment(0)
C
0

Instead of using @XmlRootElement, use @jakarta.xml.bind.annotation.XmlRootElement This is such a silly thing that solved my problem. This is so frustrating I spent hours solving this and this freaking small thing solved it. Please confirm if my answer helped you. Thanks.

Cavender answered 29/12, 2021 at 22:40 Comment(0)
J
0

In case you need JAXB serialization (also good from the testing perspective):

  1. Implement the MessageBodyWriter interface for a given type:
@Provider
@Produces("application/xml")
public class MyDataJaxbMessageBodyWriter implements MessageBodyWriter<MyData> {

  @Override
  public boolean isWriteable(
      Class<?> aClass, Type type, Annotation[] annotations, MediaType mediaType) {
    return aClass == MyData.class;
  }

  @Override
  public long getSize(MyData data, Class<?> type, Type genericType,
      Annotation[] annotations, MediaType mediaType) {
    // deprecated by JAX-RS 2.0 and ignored by Jersey runtime
    return 0;
  }

  @Override
  public void writeTo(
      MyData data,
      Class<?> aClass,
      Type type,
      Annotation[] annotations,
      MediaType mediaType,
      MultivaluedMap<String, Object> multivaluedMap,
      OutputStream outputStream)
      throws WebApplicationException {
    try {
      JAXBContext jaxbContext = JAXBContext.newInstance(MyData.class);
      jaxbContext.createMarshaller().marshal(data, outputStream);
    } catch (JAXBException jaxbException) {
      throw new RuntimeException("Error serializing a MyData.class to the output stream", jaxbException);
    }
  }
}

NB: Make sure you've annotated your implementation with:

 @Provider
 @Produces("application/xml")
  1. Register your writer with Jersey (in the main app's run method):
environment.jersey().register(MyDataJaxbMessageBodyWriter.class);
June answered 5/10, 2023 at 13:31 Comment(1)
In section 8.2.1 of the Jersey documentation it says: "Please note, that this is only a demonstration of how to write a custom entity provider. Jersey already contains default support for entity providers that can serialize JAXB beans into XML." This makes it sound like "it should just work", and in fact JSON works well, but XML upon which some JSON implementations seem to be based, does not work and it is not clear why. I suspect the javax jakarta transition or some dependency issue.Aluminize

© 2022 - 2024 — McMap. All rights reserved.