Java JAX-RS(Jersey 2实现)使用URL扩展名.xml或.json进行内容协商

Java JAX-RS(Jersey 2实现)使用URL扩展名.xml或.json进行内容协商,java,rest,jax-rs,jersey-2.0,content-type,jersey,Java,Rest,Jax Rs,Jersey 2.0,Content Type,Jersey,我看到了一个JavaRESTfulWebService,它允许在URL中请求内容类型,并在末尾添加一个扩展名,例如 .xml .json 这是我在自己的Web服务中努力实现的内容协商风格 我知道,@产生了注释,而且一个方法可以通过添加一个Accept头,比如说使用Chrome扩展名Postman,用(value={})语法解析多个类型 但我不知道如何有效地从一个方法中提取信息,然后委托给另一个方法 我假设正则表达式可以与@Path和@PathParam一起使用,但我的尝试还没有成功 有人能举

我看到了一个JavaRESTfulWebService,它允许在URL中请求内容类型,并在末尾添加一个扩展名,例如

  • .xml
  • .json
这是我在自己的Web服务中努力实现的内容协商风格

我知道,
@产生了
注释,而且一个方法可以通过添加一个Accept头,比如说使用Chrome扩展名Postman,用
(value={})
语法解析多个类型

但我不知道如何有效地从一个方法中提取信息,然后委托给另一个方法

我假设正则表达式可以与
@Path
@PathParam
一起使用,但我的尝试还没有成功

有人能举个例子吗


这是我迄今为止的尝试:

package com.extratechnology.caaews;

import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;

import com.extratechnology.caaews.model.Log;


@Path("et")
@Produces(MediaType.APPLICATION_JSON)
public class CAAEWS {


    @GET
    @Path("\\.{format}")
    @Produces(value = {MediaType.APPLICATION_JSON, MediaType.TEXT_XML})
    public Log getLog(
            @PathParam("format") String format
    ){
        Log result = null;
        switch (format) {
        case "json":
            result = this.getJSON();
        case "xml":
            result = this.getXML();
        }
        return result;
    }

    @GET
    @Produces(MediaType.APPLICATION_JSON)
    public Log getJSON() {
        return new Log("JSON!");
    }

    @GET
    @Produces(MediaType.TEXT_XML)
    public Log getXML() {
        return new Log("XML!");
    }

}


通过使用以下方法创建Maven项目(类似,但更为最新),可以从Spring工具套件/Eclipse设置该项目:

  • org.glassfish.jersey.archetypes
  • jersey.quickstart.webapp
  • 2.26
然后取消对pom.xml中用于启用JSON支持的部分的注释,这将有效地为WAR添加更多JAR

我发现我也有一些严重的BCEL错误,并且必须在catalina.properties文件的键下添加一些条目:

tomcat.util.scan.StandardJarScanFilter.jarsToSkip=\
....
javax.json-api-1.1.jar, javax.json.bind-api-1.0.jar, javax.json-1.1.jar, \
yasson-1.0.jar

收益率:

{"log":"JSON!"}
HTTP Status 404 - Not Found

收益率:

{"log":"JSON!"}
HTTP Status 404 - Not Found

我还想知道是否有某种HTTP拦截器类型的方法来解决这个问题。我的Java有点生疏,但它是servlet过滤器,还是类似于AOP的建议


多亏@user1803551,我在switch语句中加入了中断符

多亏了@callmepills,我对代码做了一些调整

类级别的@Path注释现在具有以下内容。 @产生(值={MediaType.APPLICATION\u JSON,MediaType.TEXT\u XML})

getLog@Path注释是“{format}”

为了调用和委托getLog,必须对URL使用以下语法:


在路径中需要一个“/”不是我想要的,所以我想我可能必须解决servlet过滤器而不是@PathParam方法。

您是否尝试过在类级别去掉
@path
注释?然后,您的方法级注释将是:

@Path("et.{format}")
我认为您当前的实现正在创建一个子资源,它与以下路径匹配:

/et/{format}

您的JAX-RS代码有几个问题:

@Path中的正则表达式
@Path
注释的语法仅在参数模板内部和
字符之后解析正则表达式。您试图在参数模板
“\\.{format}”之外使用正则表达式,因此它不会将其解析为正则表达式

路径分辨率 一个方法的路径包括类路径的段和它自己的路径段。当您试图调用
/et.{format}
时,您的代码建议路径
/et/{format}
,该路径未在任何地方定义,因此为404


下面是一个符合您的代码的示例:

@Path("et")
public class Resource {

    private static final String JSON = "json";
    private static final String XML = "xml";

    @GET
    @Path(".{format:(" + JSON + "|" + XML + ")}")
    @Produces(value = { MediaType.APPLICATION_JSON, MediaType.TEXT_XML }) // not XML?
    public String getLog(@PathParam("format") String format) {
        switch (format) {
            case JSON:
                this.getJSON();
                break;
            case XML:
                this.getXML();
        }
        return format;
    }

    @GET
    @Produces(MediaType.APPLICATION_JSON)
    public void getJSON() {
        System.out.println("in JSON");
    }

    @GET
    @Path("otherPath")
    @Produces(MediaType.APPLICATION_XML)
    public void getXML() {
        System.out.println("in XML");
    }
}
您的有效请求现在将是:

  • (JSON通过
    getJSON
  • (XML通过
    getXML
  • (XML通过
    getLog
  • (JSON通过
    getLog
根据需要更改路径。我对XML方法使用了
“otherPath”
,因为它不能与空路径JSON方法冲突。我不推荐这个公约

注意事项:

  • 开关
    语句中使用
    中断
  • 为了减少出现错误的机会,可以像我对自定义格式类型所做的那样,对可重用字符串使用常量等。一个
    enum
    会更好
编辑:

现在请求的路径是
/et/{format}
。如果我们扩展path参数的范围以包括整个段
{format}
,然后以编程方式提取格式,则可以实现这一点:

@GET
@Path("{segment:[a-zA-Z0-9_]*\\.(" + JSON + "|" + XML + ")}")
@Produces(value = { MediaType.APPLICATION_JSON, MediaType.TEXT_XML })
public String getLog(@PathParam("segment") String segment) {
    String format = segment.substring(segment.indexOf('.') + 1);
    switch (format) {
        case JSON:
            this.getJSON();
            break;
        case XML:
            this.getXML();
    }
    return format;
}
regex
[a-zA-Z0-9.]*
表示任何字母数字或下划线一次或多次。你可以用你想要的任何限制来替换那部分。请参考URL规范以获取允许的字符。

当我在Google上搜索“servlet filter with jax rs example”时,它位于列表的顶部。粗略地看一下代码,我认为这符合我的需要


这是我的解决方案(到目前为止……见脚注警告)

web.xml

<?xml version="1.0" encoding="UTF-8"?>
<!-- This web.xml file is not required when using Servlet 3.0 container,
     see implementation details http://jersey.java.net/nonav/documentation/latest/jax-rs.html -->
<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">

  <filter>
        <filter-name>accept-filter</filter-name>
        <filter-class>com.extratechnology.filters.AcceptFilter</filter-class>
        <init-param>
            <param-name>xml</param-name>
            <param-value>text/xml</param-value>
        </init-param>
        <init-param>
            <param-name>json</param-name>
            <param-value>application/json</param-value>
        </init-param>
    </filter>
    <filter-mapping>
        <filter-name>accept-filter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
    <servlet>
        <servlet-name>Jersey Web Application</servlet-name>
        <servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
        <init-param>
            <param-name>jersey.config.server.provider.packages</param-name>
            <param-value>com.extratechnology.caaews</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>Jersey Web Application</servlet-name>
        <url-pattern>/webapi/*</url-pattern>
    </servlet-mapping>
</web-app>

Log.java

package com.extratechnology.filters;
import java.io.IOException;
import java.util.*;
import javax.servlet.*;
import javax.servlet.http.*;
public class AcceptFilter implements Filter  {
    private final Map<String,String> extensions = new HashMap<String,String>();

    public void init(FilterConfig config) throws ServletException {
        Enumeration<String> exts = config.getInitParameterNames();
        while (exts.hasMoreElements()) {
            String ext = exts.nextElement();
            if (ext != null && !ext.isEmpty()) {
                this.extensions.put(ext.toLowerCase(), config.getInitParameter(ext));
            }
        }
    }

    public void destroy() {}

    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        HttpServletRequest httpRequest = (HttpServletRequest)request;
        String uri = httpRequest.getRequestURI();
        String ext = this.getExtension(uri);
        String accept = this.extensions.get(ext);

        if (accept == null) {
            accept = httpRequest.getHeader("accept");
            if (accept != null && accept.indexOf("text/html") > 0) {
                // patch WebKit-style Accept headers by elevating "text/html"
                accept = "text/html,"+accept;
                request = new RequestWrapper(httpRequest, uri, accept);
            }
        } else {
            // remove extension and remap the Accept header
            uri = uri.substring(0, uri.length() - ext.length()-1);
            request = new RequestWrapper(httpRequest, uri, accept);
        }

        // add "Vary: accept" to the response headers
        HttpServletResponse httpResponse = (HttpServletResponse)response;
        httpResponse.addHeader("Vary", "accept");

        chain.doFilter(request, response);
    }

    private String getExtension(String path) {
        String result = "";
        int index = path.lastIndexOf('.');
        if (!(index < 0 || path.lastIndexOf('/') > index)) {
            result =  path.substring(index+1).toLowerCase();
        }
        return result;
    }

    private static class RequestWrapper extends HttpServletRequestWrapper {

        private final String uri;
        private final String accept;

        public RequestWrapper(HttpServletRequest request, String uri, String accept) {
            super(request);

            this.uri = uri;
            this.accept = accept;
        }

        @Override
        public String getRequestURI() {
            return this.uri;
        }
        @Override
        public Enumeration<String> getHeaders(String name) {
            Enumeration<String> result;
            if ("accept".equalsIgnoreCase(name)) {
                Vector<String> values = new Vector<String>(1);
                values.add(this.accept);
                result = values.elements();
            } else {
                result =  super.getHeaders(name);       
            }
            return result;
        }
    }
}
package com.extratechnology.caaews;

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

import com.extratechnology.caaews.model.Log;


@Path("et")
@Produces(value = {MediaType.APPLICATION_JSON, MediaType.TEXT_XML})
public class CAAEWS {

    @GET
    @Produces(MediaType.APPLICATION_JSON)
    public Log getJSON() {
        return new Log("JSON!");
    }

    @GET
    @Produces(MediaType.TEXT_XML)
    public Log getXML() {
        return new Log("XML!");
    }

}
package com.extratechnology.caaews.model;

import javax.xml.bind.annotation.XmlRootElement;

@XmlRootElement
public class Log {
    private String log;

    public Log(String log) {
        this.log = log;
    }

    public String getLog() {
        return log;
    }

    public void setLog(String log) {
        this.log = log;
    }

}
package com.extratechnology.caaews.exception;

import javax.ws.rs.core.Response;
import javax.ws.rs.core.Response.Status;
import javax.ws.rs.ext.ExceptionMapper;
import javax.ws.rs.ext.Provider;

import com.extratechnology.caaews.model.ErrorMessage;

@Provider
public class GenericExceptionMapper implements ExceptionMapper<Throwable>{

    @Override
    public Response toResponse(Throwable ex) {
        System.out.println("Stack Trace:");
        ex.printStackTrace();
        System.out.println("Cause:");
        Throwable cause = ex.getCause();
        if (cause != null) {
            cause.printStackTrace();    
        }
        ErrorMessage message = new ErrorMessage(
                ex.getMessage(),
                GenericExceptionMapper.getStackTrack(ex),
                cause.getMessage(),
                GenericExceptionMapper.getStackTrack(cause),
                Status.INTERNAL_SERVER_ERROR.getStatusCode()
                );
        return Response
                .status(Status.INTERNAL_SERVER_ERROR)
                .entity(message)
                .build();
    }

    private static String getStackTrack(Throwable ex) {
        StringBuilder sb = new StringBuilder();
        String ls = System.lineSeparator();
        if (ex != null) {
            StackTraceElement[] steAll = ex.getStackTrace();
            for (StackTraceElement ste : steAll) {
                sb.append(ste.toString());
                sb.append(ls);
            }   
        }
        return sb.toString();
    }
}

唯一让我稍感兴趣的是HTTP有两种XML内容类型

  • 文本/xml
  • 应用程序/xml
它在web.xml中是可配置的,但我必须调整注释。为什么是这两个

--

脚注:

写了这篇文章之后,我现在发现我收到了HTTP 500错误。 在Eclipse中运行服务器时,日志似乎位于某个模糊的文件夹中:

Documents\workspace-sts-3.8.3.RELEASE\.metadata\.plugins\org.eclipse.wst.server.core\tmp1\logs
我把它写进日志:

0:0:0:0:0:0:0:1 - - [25/Nov/2017:16:56:00 +0000] "GET /caaews/webapi/et.xml HTTP/1.1" 500 1082
有人知道如何获得更合理的日志信息吗?或者我需要做什么来捕获更有意义的堆栈跟踪


似乎Log类需要一个无参数构造函数来克服这个问题。但我承认,@peeskillet的答案要简单得多,并且使用内置的功能


在看了一些示例之后,我还想知道javax.servlet.filters是否不能很好地与JAX-RS2.0配合使用


根据这个问题的其他相关答案/评论,我最终实现了一个异常处理程序,因此您可以在Jersey获得有关HTTP 500消息的更多信息

下面的代码有助于指出需要无参数构造函数的Log.java的方法

错误消息a
This XML file does not appear to have any style information associated with it. The document tree is shown below.
<errorMessage>
<cause>1 counts of IllegalAnnotationExceptions</cause>
<causeStackTrace>
com.sun.xml.internal.bind.v2.runtime.IllegalAnnotationsException$Builder.check(Unknown Source) com.sun.xml.internal.bind.v2.runtime.JAXBContextImpl.getTypeInfoSet(Unknown Source) com.sun.xml.internal.bind.v2.runtime.JAXBContextImpl.<init>(Unknown Source) com.sun.xml.internal.bind.v2.runtime.JAXBContextImpl.<init>(Unknown Source) com.sun.xml.internal.bind.v2.runtime.JAXBContextImpl$JAXBContextBuilder.build(Unknown Source) com.sun.xml.internal.bind.v2.ContextFactory.createContext(Unknown Source) sun.reflect.GeneratedMethodAccessor20.invoke(Unknown Source) sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) java.lang.reflect.Method.invoke(Unknown Source) javax.xml.bind.ContextFinder.newInstance(Unknown Source) javax.xml.bind.ContextFinder.newInstance(Unknown Source) javax.xml.bind.ContextFinder.find(Unknown Source) javax.xml.bind.JAXBContext.newInstance(Unknown Source) javax.xml.bind.JAXBContext.newInstance(Unknown Source) org.glassfish.jersey.jaxb.internal.AbstractJaxbProvider.getStoredJaxbContext(AbstractJaxbProvider.java:312) org.glassfish.jersey.jaxb.internal.AbstractJaxbProvider.getJAXBContext(AbstractJaxbProvider.java:297) org.glassfish.jersey.jaxb.internal.AbstractJaxbProvider.getMarshaller(AbstractJaxbProvider.java:264) org.glassfish.jersey.jaxb.internal.AbstractJaxbProvider.getMarshaller(AbstractJaxbProvider.java:231) org.glassfish.jersey.jaxb.internal.AbstractRootElementJaxbProvider.writeTo(AbstractRootElementJaxbProvider.java:175) org.glassfish.jersey.message.internal.WriterInterceptorExecutor$TerminalWriterInterceptor.invokeWriteTo(WriterInterceptorExecutor.java:266) org.glassfish.jersey.message.internal.WriterInterceptorExecutor$TerminalWriterInterceptor.aroundWriteTo(WriterInterceptorExecutor.java:251) org.glassfish.jersey.message.internal.WriterInterceptorExecutor.proceed(WriterInterceptorExecutor.java:163) org.glassfish.jersey.server.internal.JsonWithPaddingInterceptor.aroundWriteTo(JsonWithPaddingInterceptor.java:109) org.glassfish.jersey.message.internal.WriterInterceptorExecutor.proceed(WriterInterceptorExecutor.java:163) org.glassfish.jersey.server.internal.MappableExceptionWrapperInterceptor.aroundWriteTo(MappableExceptionWrapperInterceptor.java:85) org.glassfish.jersey.message.internal.WriterInterceptorExecutor.proceed(WriterInterceptorExecutor.java:163) org.glassfish.jersey.message.internal.MessageBodyFactory.writeTo(MessageBodyFactory.java:1135) org.glassfish.jersey.server.ServerRuntime$Responder.writeResponse(ServerRuntime.java:662) org.glassfish.jersey.server.ServerRuntime$Responder.processResponse(ServerRuntime.java:395) org.glassfish.jersey.server.ServerRuntime$Responder.process(ServerRuntime.java:385) org.glassfish.jersey.server.ServerRuntime$1.run(ServerRuntime.java:280) org.glassfish.jersey.internal.Errors$1.call(Errors.java:272) org.glassfish.jersey.internal.Errors$1.call(Errors.java:268) org.glassfish.jersey.internal.Errors.process(Errors.java:316) org.glassfish.jersey.internal.Errors.process(Errors.java:298) org.glassfish.jersey.internal.Errors.process(Errors.java:268) org.glassfish.jersey.process.internal.RequestScope.runInScope(RequestScope.java:289) org.glassfish.jersey.server.ServerRuntime.process(ServerRuntime.java:256) org.glassfish.jersey.server.ApplicationHandler.handle(ApplicationHandler.java:703) org.glassfish.jersey.servlet.WebComponent.serviceImpl(WebComponent.java:416) org.glassfish.jersey.servlet.WebComponent.service(WebComponent.java:370) org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:389) org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:342) org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:229) org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:291) org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206) org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52) org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:239) org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206) org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:217) org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:106) org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:502) org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:142) org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:79) org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:616) org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:88) org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:518) org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1091) org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:673) org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1500) org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.run(NioEndpoint.java:1456) java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source) java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source) org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) java.lang.Thread.run(Unknown Source)
</causeStackTrace>
<errorCode>500</errorCode>
<errorMessage>HTTP 500 Internal Server Error</errorMessage>
<errorStackTrace>
org.glassfish.jersey.jaxb.internal.AbstractRootElementJaxbProvider.writeTo(AbstractRootElementJaxbProvider.java:183) org.glassfish.jersey.message.internal.WriterInterceptorExecutor$TerminalWriterInterceptor.invokeWriteTo(WriterInterceptorExecutor.java:266) org.glassfish.jersey.message.internal.WriterInterceptorExecutor$TerminalWriterInterceptor.aroundWriteTo(WriterInterceptorExecutor.java:251) org.glassfish.jersey.message.internal.WriterInterceptorExecutor.proceed(WriterInterceptorExecutor.java:163) org.glassfish.jersey.server.internal.JsonWithPaddingInterceptor.aroundWriteTo(JsonWithPaddingInterceptor.java:109) org.glassfish.jersey.message.internal.WriterInterceptorExecutor.proceed(WriterInterceptorExecutor.java:163) org.glassfish.jersey.server.internal.MappableExceptionWrapperInterceptor.aroundWriteTo(MappableExceptionWrapperInterceptor.java:85) org.glassfish.jersey.message.internal.WriterInterceptorExecutor.proceed(WriterInterceptorExecutor.java:163) org.glassfish.jersey.message.internal.MessageBodyFactory.writeTo(MessageBodyFactory.java:1135) org.glassfish.jersey.server.ServerRuntime$Responder.writeResponse(ServerRuntime.java:662) org.glassfish.jersey.server.ServerRuntime$Responder.processResponse(ServerRuntime.java:395) org.glassfish.jersey.server.ServerRuntime$Responder.process(ServerRuntime.java:385) org.glassfish.jersey.server.ServerRuntime$1.run(ServerRuntime.java:280) org.glassfish.jersey.internal.Errors$1.call(Errors.java:272) org.glassfish.jersey.internal.Errors$1.call(Errors.java:268) org.glassfish.jersey.internal.Errors.process(Errors.java:316) org.glassfish.jersey.internal.Errors.process(Errors.java:298) org.glassfish.jersey.internal.Errors.process(Errors.java:268) org.glassfish.jersey.process.internal.RequestScope.runInScope(RequestScope.java:289) org.glassfish.jersey.server.ServerRuntime.process(ServerRuntime.java:256) org.glassfish.jersey.server.ApplicationHandler.handle(ApplicationHandler.java:703) org.glassfish.jersey.servlet.WebComponent.serviceImpl(WebComponent.java:416) org.glassfish.jersey.servlet.WebComponent.service(WebComponent.java:370) org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:389) org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:342) org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:229) org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:291) org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206) org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52) org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:239) org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206) org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:217) org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:106) org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:502) org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:142) org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:79) org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:616) org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:88) org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:518) org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1091) org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:673) org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1500) org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.run(NioEndpoint.java:1456) java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source) java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source) org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) java.lang.Thread.run(Unknown Source)
</errorStackTrace>
</errorMessage>
txt : text/plain, xml : application/xml
final Map<String, MediaType> mediaTypeMappings = new HashMap<>();
mediaTypeMappings.put("xml", MediaType.APPLICATION_XML_TYPE);
mediaTypeMappings.put("json", MediaType.APPLICATION_JSON_TYPE);

final ResourceConfig rc = new ResourceConfig()
        .packages("com.example.jersey")
        .property(ServerProperties.MEDIA_TYPE_MAPPINGS, mediaTypeMappings);
<servlet>
    <servlet-name>JerseyApplication</servlet-name>
    <servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
    <init-param>
        <param-name>jersey.config.server.provider.packages</param-name>
        <param-value>com.example</param-value>
    </init-param>
    <init-param>
        <param-name>jersey.config.server.mediaTypeMappings</param-name>
        <param-value>xml:application/xml, json:application/json</param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
</servlet>