Ошибка HTTP 415 Неподдерживаемый тип носителя при работе службы REST с параметром XML (Jersey + Jetty)

Я разработал REST-сервис с Jersey и Jetty. В сервисе есть две операции:

  • ПОЛУЧИТЬ проверку ресурсов
  • POST для сотрудника ресурса, который использует экземпляр Employee, отправленный в виде XML

Когда я вызываю тестовую операцию, все работает, как и ожидалось, и я вижу, что служба выводит печатное сообщение. Однако, когда я пытаюсь вызвать операцию POST, я получаю ошибку HTTP 415.

Чтобы скомпилировать проект и создать файл jar, я использую maven, и это содержимое файла pom.xml:

<?xml version="1.0" encoding="UTF-8"?>
<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/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.test.app</groupId>
    <artifactId>Service</artifactId>
    <version>1.0</version>
    <packaging>jar</packaging>
    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <maven.compiler.source>1.8</maven.compiler.source>
        <maven.compiler.target>1.8</maven.compiler.target>
        <maven-compiler-plugin.version>3.6.0</maven-compiler-plugin.version>
        <maven-shade-plugin.version>2.4.3</maven-shade-plugin.version>
        <maven-resources-plugin.version>3.0.1</maven-resources-plugin.version>
        <maven-clean-plugin.version>3.0.0</maven-clean-plugin.version>
        <maven-war-plugin.version>3.0.0</maven-war-plugin.version>
        <tomcat7-maven-plugin.version>2.1</tomcat7-maven-plugin.version>
        <maven-jaxb2-plugin.version>0.12.1</maven-jaxb2-plugin.version>
        <maven-surefire-plugin.version>2.19.1</maven-surefire-plugin.version>


        <jersey.version>2.26</jersey.version>
        <jetty.version>9.4.3.v20170317</jetty.version>
    </properties>

    <!-- DEPENDENCIES -->
    <dependencies>

        <!-- REST Service-->
        <dependency>
            <groupId>org.eclipse.jetty</groupId>
            <artifactId>jetty-server</artifactId>
            <version>${jetty.version}</version>
        </dependency>
        <dependency>
            <groupId>org.eclipse.jetty</groupId>
            <artifactId>jetty-servlet</artifactId>
            <version>${jetty.version}</version>
        </dependency>
        <dependency>
            <groupId>org.glassfish.jersey.containers</groupId>
            <artifactId>jersey-container-servlet-core</artifactId>
            <version>${jersey.version}</version>
        </dependency>
        <dependency>
            <groupId>org.glassfish.jersey.containers</groupId>
            <artifactId>jersey-container-jetty-http</artifactId>
            <version>${jersey.version}</version>
        </dependency>
        <dependency>
            <groupId>org.eclipse.jetty</groupId>
            <artifactId>jetty-util</artifactId>
            <version>${jetty.version}</version>
        </dependency>        
        <dependency>
            <groupId>org.glassfish.jersey.core</groupId>
            <artifactId>jersey-server</artifactId>
            <version>${jersey.version}</version>
        </dependency>
        <dependency>
            <groupId>org.glassfish.jersey.inject</groupId>
            <artifactId>jersey-hk2</artifactId>
            <version>${jersey.version}</version>
        </dependency>
        <dependency>
            <groupId>org.glassfish.jersey.media</groupId>
            <artifactId>jersey-media-moxy</artifactId>
            <version>${jersey.version}</version>
        </dependency>
    </dependencies>

    <!-- BUILD -->
    <build>
        <finalName>${project.artifactId}</finalName>
        <plugins>
            <plugin>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>${maven-compiler-plugin.version}</version>
                <configuration>
                    <source>${maven.compiler.source}</source>
                    <target>${maven.compiler.target}</target>
                </configuration>
            </plugin>

            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-dependency-plugin</artifactId>
                <executions>
                    <execution>
                        <id>copy</id>
                        <phase>packaging</phase>
                        <goals>
                            <goal>copy-dependencies</goal>
                        </goals>
                        <configuration>
                            <outputDirectory>${project.build.directory}/lib</outputDirectory>
                            <silent>true</silent>
                        </configuration>
                    </execution>
                </executions>
            </plugin>

            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-shade-plugin</artifactId>
                <version>${maven-shade-plugin.version}</version>
                <executions>
                    <execution>
                        <phase>package</phase>
                        <goals>
                            <goal>shade</goal>
                        </goals>
                        <configuration>
                            <finalName>${project.artifactId}</finalName>
                            <filters>
                                <filter>
                                    <artifact>*:*</artifact>
                                    <excludes>
                                        <exclude>META-INF/*.SF</exclude>
                                        <exclude>META-INF/*.DSA</exclude>
                                        <exclude>META-INF/*.RSA</exclude>
                                    </excludes>
                                </filter>
                            </filters>
                        </configuration>
                    </execution>
                </executions>
            </plugin>

        </plugins>
    </build>
</project>

А это код двух классов, используемых службой: Служба (реализация службы)

package com.test.app;

import java.util.List;

import javax.ws.rs.Consumes;
import javax.ws.rs.GET;
import javax.ws.rs.PUT;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;

import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.Response.Status;

import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.servlet.ServletContextHandler;
import org.eclipse.jetty.servlet.ServletHolder;

import org.glassfish.jersey.servlet.ServletContainer;


    @Path("/api")
    public class Service {

        @GET
        @Path("test/")
        public Response test() {
            System.out.println("test invoked");
            return Response.ok().build();
        }

        @POST
        @Path("employee/")
        @Consumes(MediaType.APPLICATION_XML)
        @Produces(MediaType.APPLICATION_XML)
        public Response getEmployee(Employee employee) {
            employee.setEmployeeName(employee.getEmployeeName() + " Welcome");
            return Response.status(Status.OK).entity(employee).build();
        }

        public static void main(String[] args) throws Exception {
            ServletContextHandler context = new ServletContextHandler(ServletContextHandler.SESSIONS);
            context.setContextPath("/");

            int port = 46100;
            Server jettyServer = new Server(port);
            jettyServer.setHandler(context);
            //org.eclipse.jetty.util.log.Log.getRootLogger().setDebugEnabled(true);

            ServletHolder jerseyServlet = context.addServlet(ServletContainer.class, "/*");
            jerseyServlet.setInitOrder(0);

            // Tells the Jersey Servlet which REST service/class to load.
            jerseyServlet.setInitParameter("jersey.config.server.provider.classnames", Service.class.getCanonicalName());

            try {
                jettyServer.start();
                jettyServer.join();
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                jettyServer.destroy();
            }
        }
    }

и Сотрудник (Объект передается в качестве параметра функции)

package com.test.app;

import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;


@XmlRootElement(name = "Employee")
public class Employee {

    String employeeName;

    @XmlElement
    public String getEmployeeName() {
        return employeeName;
    }

    public void setEmployeeName(String employeeName) {
        this.employeeName = employeeName;
    }
}

Чтобы убедиться, что выполнение операции работает должным образом, я запускаю следующую команду curl:

curl -v -XPOST localhost:46100/api/employee -H "Content-type: application/xml" -d "<?xml version=\"1.0\" encoding=\"UTF-8\"?><Employee>
 <employeeName>Jack</employeeName>
</Employee>"

И ответ, который я получаю, это ошибка HTTP 415.

Я подозреваю, что мне не хватает некоторой зависимости от файла maven, необходимого только во время выполнения, который содержит преобразование из файла XML в фактический объект Employee.

Можете ли вы предоставить Content-type как application/xml при вызове остальных, а также добавить @Produces(MediaType.APPLICATION_XML) в метод getEmployee

Sambit 22.05.2019 14:48

Я получаю тот же результат. Я редактирую вопрос, чтобы добавить заголовок в команду curl

Francesc Lordan 22.05.2019 14:58

Добавьте @Produces(MediaType.APPLICATION_XML) в метод getEmployee. Проверьте после добавления, работает нормально или нет.

Sambit 22.05.2019 14:59

Упс! Я пробовал это на предыдущей версии, и я думал, что это уже было там. Я только что добавил его обратно, но проблема остается

Francesc Lordan 22.05.2019 15:08

Вы пробовали это с помощью клиента Postman rest?

Sambit 22.05.2019 16:25

Вы работаете как банку или просто работаете в своей среде IDE?

Paul Samsotha 22.05.2019 23:09
Добавьте преобразователь служебного файла в конфигурацию вашего плагина maven shadow
Paul Samsotha 23.05.2019 04:44

Я запускаю его из файла jar с помощью команды: mvn clean package && java -cp ./target/Service.jar com.test.app.Service

Francesc Lordan 27.05.2019 18:14
Основы программирования на Java
Основы программирования на Java
Java - это высокоуровневый объектно-ориентированный язык программирования, основанный на классах.
Концепции JavaScript, которые вы должны знать как JS программист!
Концепции JavaScript, которые вы должны знать как JS программист!
JavaScript (Js) - это язык программирования, объединяющий HTML и CSS с одной из основных технологий Всемирной паутины. Более 97% веб-сайтов используют...
0
8
511
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Я попробовал ваш код. Это абсолютно нормально. Я пробовал в Post REST Client, он работает нормально. Проблема с командой curl. Найдите ниже команду curl для тестирования.

curl -XPOST http://localhost:46100/api/employee -H "Content-type: application/xml" -d "<?xml version=\"1.0\" encoding=\"UTF-8\"?><Employee><employeeName>Jack</employeeName></Employee>"

Я сделал следующие модификации.

  • Удалена опция -v
  • Добавлен http:// в URL

В случае веб-сервиса RESTful вы можете использовать следующие инструменты для тестирования, которые действительно полезны.

Проверьте и дайте мне знать, я тестирую на компьютере с Windows команду curl.

Sambit 22.05.2019 17:28

Проверьте эту ссылку, вы узнаете. github.com/debjava/jetty-джерси-остальное

Sambit 22.05.2019 19:48

Если вы используете eclipse, вы можете импортировать проект как проект maven.

Sambit 22.05.2019 19:58

Я пытаюсь запустить проект по ссылке на github, и у меня возникает та же проблема.

Francesc Lordan 27.05.2019 18:20

В чем проблема ?

Sambit 27.05.2019 18:26

Судя по всему, проблема с конфигурацией файла pom.

Francesc Lordan 27.05.2019 18:43
Ответ принят как подходящий

Неправильная конфигурация плагина maven-shade. Заменив его на

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-shade-plugin</artifactId>
    <version>${maven-shade-plugin.version}</version>
    <configuration>
        <createDependencyReducedPom>true</createDependencyReducedPom>
        <filters>
            <filter>
                <artifact>*:*</artifact>
                <excludes>
                    <exclude>META-INF/*.SF</exclude>
                    <exclude>META-INF/*.DSA</exclude>
                    <exclude>META-INF/*.RSA</exclude>
                </excludes>
            </filter>
        </filters>
    </configuration>
    <executions>
        <execution>
            <phase>package</phase>
            <goals>
                <goal>shade</goal>
            </goals>
            <configuration>
                <transformers>
                    <transformer implementation="org.apache.maven.plugins.shade.resource.ServicesResourceTransformer"/>
                    <transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer"/>
               </transformers>
           </configuration>
       </execution>
   </executions>
</plugin>

решает проблему

Другие вопросы по теме