Jersey(1.19.1) - XML Support

时间:2022-12-19 16:18:41

As you probably already know, Jersey uses MessageBodyWriters and MessageBodyReaders to parse incoming request and create outgoing responses. Every user can create its own representation but... this is not recommended way how to do things. XML is proven standard for interchanging information, especially in web services. Jerseys supports low level data types used for direct manipulation and JAXB XML entities.

Low level XML support

Jersey currently support several low level data types: StreamSourceSAXSourceDOMSource and Document. You can use these types as return type or method (resource) parameter. Lets say we want to test this feature and we have helloworld sample as starting point. All we need to do is add methods (resources) which consumes and produces XML and types mentioned above will be used.

@Path("1")
@POST
public StreamSource get1(StreamSource streamSource) {
return streamSource;
} @Path("2")
@POST
public SAXSource get2(SAXSource saxSource) {
return saxSource;
} @Path("3")
@POST
public DOMSource get3(DOMSource domSource) {
return domSource;
} @Path("4")
@POST
public Document get4(Document document) {
return document;
}

Both MessageBodyReaders and MessageBodyWriters are used in this case, all we need is do POST request with some XML document as a request entity. I want to keep this as simple as possible so I'm going to send only root element with no content: "<test />". You can create Jersey client to do that or use some other tool, for example curl as I did. (curl -v http://localhost:9998/helloworld/1 -d "<test />"). You should get exactly same XML from our service as is present in the request; in this case, XML headers are added to response but content stays. Feel free to iterate through all resources.

Getting started with JAXB

Good start for people which already have some experience with JAXB annotations is JAXB sample. You can see various usecases there. This text is mainly meant for those who don't have prior experience with JAXB. Don't expect that all possible annotations and their combinations will be covered in this chapter, JAXB (JSR 222 implementation) is pretty complex and comprehensive. But if you just want to know how you can interchange XML messages with your REST service, you are looking at right chapter.

Lets start with simple example. Lets say we have class Planet and service which produces "Planets":

// Planet class
@XmlRootElement
public class Planet {
public int id;
public String name;
public double radius;
} // Resource class
@Path("planet")
public class Resource { @GET
@Produces(MediaType.APPLICATION_XML)
public Planet getPlanet() {
Planet p = new Planet();
p.id = 1;
p.name = "Earth";
p.radius = 1.0; return p;
}
}

You can see there is some extra annotation declared on Planet class. Concretely XmlRootelement. What it does? This is a JAXB annotation which maps java class to XML element. We don't need specify anything else, because Planet is very simple class and all fields are public. In this case, XML element name will be derived from class name or you can set name property: @XmlRootElement(name="yourName").

Our resource class will respond to GET /planet with

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<planet>
<id>1</id>
<name>Earth</name>
<radius>1.0</radius>
</planet>

which might be exactly what we want... or not. Or we might not really care, because we can use Jersey client for making requests to this resource and this is easy as: Planet planet = webResource.path("planet").accept(MediaType.APPLICATION_XML_TYPE).get(Planet.class);. There is pre-created WebResource object which points to our applications context root and we simpli add path (in our clase its "planet"), accept header (not mandatory, but service could provide different content based on this header; for example text/html can be served for web browsers) and at the end we specify that we are expecting Planet class via GET request.

There may be need for not just producing XML, we might want to consume it as well.

@POST
@Consumes(MediaType.APPLICATION_XML)
public void setPlanet(Planet p) {
System.out.println("setPlanet " + p);
}

After valid request is made (with Jersey client you can do webResource.path("planet").post(p);), service will print out string representation of Planet, which can look like Planet{id=2, name='Mars', radius=1.51}.

If there is a need for some other (non default) XML representation, other JAXB annotations would need to be used. This process is usually simplified by generating java source from XML Schema which is done by xjc. Xjc is XML to java compiler and is part of JAXB. See JAXB home page for further details.

POJOs

Sometimes you can't / don't want to add JAXB annotations to source code and you still want to have resources consuming and producing XML representation of your classes. In this case, JAXBElement class should help you. Let's redo planet resource but this time we won't have XmlRootElement annotation on Planet class.

@Path("planet")
public class Resource { @GET
@Produces(MediaType.APPLICATION_XML)
public JAXBElement<Planet> getPlanet() {
Planet p = new Planet();
p.id = 1;
p.name = "Earth";
p.radius = 1.0; return new JAXBElement<Planet>(new QName("planet"), Planet.class, p);
} @POST
@Consumes(MediaType.APPLICATION_XML)
public void setPlanet(JAXBElement<Planet> p) {
System.out.println("setPlanet " + p.getValue());
}
}

As you can see, everything is little more complicated with JAXBElement. This is because now you need to explicitly set element name for Planet class XML representation. Client side is even more ugly than server side because you can't do JAXBElement<Planet>.class so Jersey client API provides way how to workaround it by declaring subclass of GenericType.

// GET
GenericType<JAXBElement<Planet>> planetType = new GenericType<JAXBElement<Planet>>() {}; Planet planet = (Planet) webResource.path("planet").accept(MediaType.APPLICATION_XML_TYPE).get(planetType).getValue();
System.out.println("### " + planet); // POST
Planet p = new Planet();
// ... webResource.path("planet").post(new JAXBElement<Planet>(new QName("planet"), Planet.class, p));

Using custom JAXBContext

In some scenarios you can take advantage of using custom JAXBContext. Creating JAXBContext is expensive operation and if you already have one created, same instance can be used by Jersey. Other possible usecase for this is when you need to set some specific things to JAXBContext, for example set different classloader.

@Provider
public class PlanetJAXBContextProvider implements ContextResolver<JAXBContext> {
private JAXBContext context = null; public JAXBContext getContext(Class<?> type) {
if(type != Planet.class)
return null; // we don't support nothing else than Planet if(context == null) {
try {
context = JAXBContext.newInstance(Planet.class);
} catch (JAXBException e) {
// log warning/error; null will be returned which indicates that this
// provider won't/can't be used.
}
}
return context;
}
}

Sample above shows simple JAXBContext creation, all you need to do is put this @Provider annotated class somewhere where Jersey can find it. Users sometimes have problems with using provider classes on client side, so just for reminder - you have to declare them in client config (cliend does not anything like package scanning done by server).

ClientConfig cc = new DefaultClientConfig();
cc.getClasses().add(PlanetJAXBContextProvider.class);
Client c = Client.create(cc);

Jersey(1.19.1) - XML Support的更多相关文章

  1. Jersey&lpar;1&period;19&period;1&rpar; - JSON Support

    Jersey JSON support comes as a set of JAX-RS MessageBodyReader<T> and MessageBodyWriter<T&g ...

  2. Jersey&lpar;1&period;19&period;1&rpar; - Hello World&comma; Get started with a Web application

    1. Maven Dependency <properties> <jersey.version>1.19.1</jersey.version> </prop ...

  3. Jersey&lpar;1&period;19&period;1&rpar; - Root Resource Classes

    Root resource classes are POJOs (Plain Old Java Objects) that are annotated with @Path have at least ...

  4. Jersey&lpar;1&period;19&period;1&rpar; - Hello World&comma; Get started with Jersey using the embedded Grizzly server

    Maven Dependencies The following Maven dependencies need to be added to the pom: <dependency> ...

  5. Jersey&lpar;1&period;19&period;1&rpar; - Deploying a RESTful Web Service

    JAX-RS provides a deployment agnostic abstract class Application for declaring root resource and pro ...

  6. Jersey&lpar;1&period;19&period;1&rpar; - Building Responses

    Sometimes it is necessary to return additional information in response to a HTTP request. Such infor ...

  7. Jersey&lpar;1&period;19&period;1&rpar; - Sub-resources

    @Path may be used on classes and such classes are referred to as root resource classes. @Path may al ...

  8. Jersey&lpar;1&period;19&period;1&rpar; - Client API&comma; Ease of use and reusing JAX-RS artifacts

    Since a resource is represented as a Java type it makes it easy to configure, pass around and inject ...

  9. Jersey&lpar;1&period;19&period;1&rpar; - Client API&comma; Overview of the API

    To utilize the client API it is first necessary to create an instance of a Client, for example: Clie ...

随机推荐

  1. 【转】Xcode 6制作动态及静态Framework

    http://years.im/Home/Article/detail/id/52.html 创建iOS动态库 新建工程并选择默认Target为Cocoa Touch Framework, 如图: 做 ...

  2. 测试V模型

    一:测试V模型 RAD(Rap Application Development 快速引用开发)模型是软件开发过程中的一个重要模型,由于模型构图形似字母V,所以又称软件开发的V模型.他通过开发和测试同时 ...

  3. SSIS 学习(9):包部署常见问题汇总【转】

    Integration Services 包在部署过程中,经常会出现这样那样的问题,让人摸不着头脑,很是烦人.下面我就将我在部署过程中,遇到的一些问题整理出来,以供大家参考. (一)SSIS包在SQL ...

  4. html5在手机端关于 map area中的自适应

    https://github.com/stowball/jQuery-rwdImageMaps用这一个插件可自适应!!!

  5. java和c&num;md5加密不同

    java的mad5加密后为32位字符串,c#直接加密后可能不是32位,位数也不确定. 普通的写法 public static string Md5(string sourcein) { var md5 ...

  6. HTML——JavaScript简介

    一.简介: JavaScript是个脚本语言,需要有宿主文件,他的宿主文件是HTML文件. JavaScript 是属于 web 的语言,它适用于 PC.笔记本电脑.平板电脑和移动电话. JavaSc ...

  7. &lbrack;string&rsqb;Reverse Words in a String

    Given an input string, reverse the string word by word. For example,Given s = "the sky is blue& ...

  8. 我的Python成长之路---第一天---Python基础(6)---2015年12月26日(雾霾)

    七.列表——list Python的列表是一种内置的数据类型,是由Python的基本数据类型组成的有序的集合.有点类似C语言的数组,但与数组不同的是,Python在定义列表的时候不用指定列表的容积(长 ...

  9. ZOJ 1119 SPF

    Tarjan算法求解割点 #include<cstdio> #include<cstring> #include<cmath> #include<vector ...

  10. HTML5 移动页面自适应手机屏幕四类方法

    1.使用meta标签:viewport H5移动端页面自适应普遍使用的方法,理论上讲使用这个标签是可以适应所有尺寸的屏幕的,但是各设备对该标签的解释方式及支持程度不同造成了不能兼容所有浏览器或系统. ...