Chapter 9. Support for Common Media Type Representations
Prev |  | Next

Links: Table of Contents | Single HTML

# Chapter 9. Support for Common Media Type Representations

## 9.1. JSON

Jersey JSON support comes as a set of extension modules where each of these modules contains an implementation of a Feature that needs to be registered into your Configurable instance (client/server). There are multiple frameworks that provide support for JSON processing and/or JSON-to-Java binding. The modules listed below provide support for JSON representations by integrating the individual JSON frameworks into Jersey. At present, Jersey integrates with the following modules to provide JSON support:

- MOXy - JSON binding support via MOXy is a default and preferred way of supporting JSON binding in your Jersey applications since Jersey 2.0. When JSON MOXy module is on the class-path, Jersey will automatically discover the module and seamlessly enable JSON binding support via MOXy in your applications. (See Section 4.3, “Auto-Discoverable Features”.)

- Java API for JSON Processing (JSON-P)

- Jackson

- Jettison

- Java API for JSON Binding (JSON-B)

### 9.1.1. Approaches to JSON Support

Each of the aforementioned extension modules uses one or more of the three basic approaches available when working with JSON representations:

- POJO based JSON binding support

- JAXB based JSON binding support

- Low-level JSON parsing & processing support

The first method is pretty generic and allows you to map any Java Object to JSON and vice versa. The other two approaches limit you in Java types your resource methods could produce and/or consume. JAXB based approach is useful if you plan to utilize certain JAXB features and support both XML and JSON representations. The last, low-level, approach gives you the best fine-grained control over the out-coming JSON data format.

#### 9.1.1.1. POJO support

POJO support represents the easiest way to convert your Java Objects to JSON and back.

Media modules that support this approach are MOXy, Jackson, and Java API for JSON Binding (JSON-B)

#### 9.1.1.2. JAXB based JSON support

Taking this approach will save you a lot of time, if you want to easily produce/consume both JSON and XML data format. With JAXB beans you will be able to use the same Java model to generate JSON as well as XML representations. Another advantage is simplicity of working with such a model and availability of the API in Java SE Platform. JAXB leverages annotated POJOs and these could be handled as simple Java beans.

A disadvantage of JAXB based approach could be if you need to work with a very specific JSON format. Then it might be difficult to find a proper way to get such a format produced and consumed. This is a reason why a lot of configuration options are provided, so that you can control how JAXB beans get serialized and de-serialized. The extra configuration options however requires you to learn more details about the framework you are using.

Following is a very simple example of how a JAXB bean could look like.

Example 9.1. Simple JAXB bean implementation

    @XmlRootElement
    public class MyJaxbBean {
        public String name;
        public int age;

        public MyJaxbBean() {} // JAXB needs this

        public MyJaxbBean(String name, int age) {
            this.name = name;
            this.age = age;
        }
    }

Using the above JAXB bean for producing JSON data format from you resource method, is then as simple as:

Example 9.2. JAXB bean used to generate JSON representation

    @GET
    @Produces("application/json")
    public MyJaxbBean getMyBean() {
        return new MyJaxbBean("Agamemnon", 32);
    }

Notice, that JSON specific mime type is specified in `@Produces` annotation, and the method returns an instance of `MyJaxbBean`, which JAXB is able to process. Resulting JSON in this case would look like:

    {"name":"Agamemnon", "age":"32"}

A proper use of JAXB annotations itself enables you to control output JSON format to certain extent. Specifically, renaming and omitting items is easy to do directly just by using JAXB annotations. For example, the following example depicts changes in the above mentioned MyJaxbBean that will result in `{"king":"Agamemnon"}` JSON output.

Example 9.3. Tweaking JSON format using JAXB

    @XmlRootElement
    public class MyJaxbBean {

        @XmlElement(name="king")
        public String name;

        @XmlTransient
        public int age;

        // several lines removed
    }

Media modules that support this approach are MOXy, Jackson, Jettison

#### 9.1.1.3. Low-level based JSON support

JSON Processing API is a new standard API for parsing and processing JSON structures in similar way to what SAX and StAX parsers provide for XML. The API is part of Jakarta EE 9 and later. Another such JSON parsing/processing API is provided by Jettison framework (which is also supported in jakartified environment). Both APIs provide a low-level access to producing and consuming JSON data structures. By adopting this low-level approach you would be working with `JsonObject` (or `JSONObject` respectively) and/or `JsonArray` (or `JSONArray` respectively) classes when processing your JSON data representations.

The biggest advantage of these low-level APIs is that you will gain full control over the JSON format produced and consumed. You will also be able to produce and consume very large JSON structures using streaming JSON parser/generator APIs. On the other hand, dealing with your data model objects will probably be a lot more complex, compared to the POJO or JAXB based binding approach. Differences are depicted at the following code snippets.

Let's start with JAXB-based approach.

Example 9.4. JAXB bean creation

    MyJaxbBean myBean = new MyJaxbBean("Agamemnon", 32);

Above you construct a simple JAXB bean, which could be written in JSON as `{"name":"Agamemnon", "age":32}`

Now to build an equivalent `JsonObject`/`JSONObject` (in terms of resulting JSON expression), you would need several more lines of code. The following example illustrates how to construct the same JSON data using the standard Jakarta EE 9 JSON-Processing API.

Example 9.5. Constructing a `JsonObject` (JSON-Processing)

    JsonObject myObject = Json.createObjectBuilder()
            .add("name", "Agamemnon")
            .add("age", 32)
            .build();

And at last, here's how the same work can be done with Jettison API.

Example 9.6. Constructing a `JSONObject` (Jettison)

    JSONObject myObject = new JSONObject();
    try {
        myObject.put("name", "Agamemnon");
        myObject.put("age", 32);
    } catch (JSONException ex) {
        LOGGER.log(Level.SEVERE, "Error ...", ex);
    }

Media modules that support the low-level JSON parsing and generating approach are Java API for JSON Processing (JSON-P) and Jettison. Unless you have a strong reason for using the non-standard Jettison API, we recommend you to use the new standard Java API for JSON Processing (JSON-P) API instead.

### 9.1.2. MOXy

#### 9.1.2.1. Dependency

To use MOXy as your JSON provider you need to add `jersey-media-moxy` module to your `pom.xml` file:

    <dependency>
        <groupId>org.glassfish.jersey.media</groupId>
        <artifactId>jersey-media-moxy</artifactId>
        <version>3.1.10</version>
    </dependency>

If you're not using Maven make sure to have all needed dependencies (see jersey-media-moxy) on the classpath.

#### 9.1.2.2. Configure and register

As stated in the Section 4.3, “Auto-Discoverable Features” as well as earlier in this chapter, MOXy media module is one of the modules where you don't need to explicitly register its `Feature`s (`MoxyJsonFeature`) in your client/server Configurable as this feature is automatically discovered and registered when you add `jersey-media-moxy` module to your class-path.

The auto-discoverable `jersey-media-moxy` module defines a few properties that can be used to control the automatic registration of `MoxyJsonFeature` (besides the generic CommonProperties.FEATURE_AUTO_DISCOVERY_DISABLE an the its client/server variants):

- CommonProperties.MOXY_JSON_FEATURE_DISABLE

- ServerProperties.MOXY_JSON_FEATURE_DISABLE

- ClientProperties.MOXY_JSON_FEATURE_DISABLE

### Note

A manual registration of any other Jersey JSON provider feature (except for Java API for JSON Processing (JSON-P)) disables the automated enabling and configuration of `MoxyJsonFeature`.

To configure MessageBodyReader<T>s / MessageBodyWriter<T>s provided by MOXy you can simply create an instance of MoxyJsonConfig and set values of needed properties. For most common properties you can use a particular method to set the value of the property or you can use more generic methods to set the property:

- MoxyJsonConfig#property(java.lang.String, java.lang.Object) - sets a property value for both Marshaller and Unmarshaller.

- MoxyJsonConfig#marshallerProperty(java.lang.String, java.lang.Object) - sets a property value for Marshaller.

- MoxyJsonConfig#unmarshallerProperty(java.lang.String, java.lang.Object) - sets a property value for Unmarshaller.

Example 9.7. MoxyJsonConfig - Setting properties.

    final Map<String, String> namespacePrefixMapper = new HashMap<String, String>();
    namespacePrefixMapper.put("http://www.w3.org/2001/XMLSchema-instance", "xsi");

    final MoxyJsonConfig configuration = new MoxyJsonConfig()
            .setNamespacePrefixMapper(namespacePrefixMapper)
            .setNamespaceSeparator(':');

In order to make `MoxyJsonConfig` visible for MOXy you need to create and register `ContextResolver<T>` in your client/server code.

Example 9.8. Creating `ContextResolver<MoxyJsonConfig>`

    final Map<String, String> namespacePrefixMapper = new HashMap<String, String>();
    namespacePrefixMapper.put("http://www.w3.org/2001/XMLSchema-instance", "xsi");

    final MoxyJsonConfig moxyJsonConfig = MoxyJsonConfig()
                .setNamespacePrefixMapper(namespacePrefixMapper)
                .setNamespaceSeparator(':');

    final ContextResolver<MoxyJsonConfig> jsonConfigResolver = moxyJsonConfig.resolver();

Another way to pass configuration properties to the underlying `MOXyJsonProvider` is to set them directly into your Configurable instance (see an example below). These are overwritten by properties set into the MoxyJsonConfig.

Example 9.9. Setting properties for MOXy providers into Configurable

    new ResourceConfig()
                                .property(MarshallerProperties.JSON_NAMESPACE_SEPARATOR, ".")
                                // further configuration

There are some properties for which Jersey sets the default value when MessageBodyReader<T> / MessageBodyWriter<T> from MOXy is used and they are:

Table 9.1. Default property values for MOXy MessageBodyReader<T> / MessageBodyWriter<T>

`jakarta.xml.bind.Marshaller#JAXB_FORMATTED_OUTPUT` | `false`
`org.eclipse.persistence.jaxb.JAXBContextProperties#JSON_INCLUDE_ROOT` | `false`
`org.eclipse.persistence.jaxb.MarshallerProperties#JSON_MARSHAL_EMPTY_COLLECTIONS` | `true`
`org.eclipse.persistence.jaxb.JAXBContextProperties#JSON_NAMESPACE_SEPARATOR` | `org.eclipse.persistence.oxm.XMLConstants#DOT`

Example 9.10. Building client with MOXy JSON feature enabled.

    final Client client = ClientBuilder.newBuilder()
            // The line below that registers MOXy feature can be
            // omitted if FEATURE_AUTO_DISCOVERY_DISABLE is
            // not disabled.
            .register(MoxyJsonFeature.class)
            .register(jsonConfigResolver)
            .build();

Example 9.11. Creating JAX-RS application with MOXy JSON feature enabled.

    // Create JAX-RS application.
    final Application application = new ResourceConfig()
            .packages("org.glassfish.jersey.examples.jsonmoxy")
            // The line below that registers MOXy feature can be
            // omitted if FEATURE_AUTO_DISCOVERY_DISABLE is
            // not disabled.
            .register(MoxyJsonFeature.class)
            .register(jsonConfigResolver);

#### 9.1.2.3. Examples

Jersey provides a JSON MOXy example on how to use MOXy to consume/produce JSON.

### 9.1.3. Java API for JSON Processing (JSON-P)

#### 9.1.3.1. Dependency

To use JSON-P as your JSON provider you need to add `jersey-media-json-processing` module to your `pom.xml` file:

    <dependency>
        <groupId>org.glassfish.jersey.media</groupId>
        <artifactId>jersey-media-json-processing</artifactId>
        <version>3.1.10</version>
    </dependency>

If you're not using Maven make sure to have all needed dependencies (see jersey-media-json-processing) on the class-path.

#### 9.1.3.2. Configure and register

As stated in Section 4.3, “Auto-Discoverable Features” JSON-Processing media module is one of the modules where you don't need to explicitly register its `Feature`s (`JsonProcessingFeature`) in your client/server Configurable as this feature is automatically discovered and registered when you add `jersey-media-json-processing` module to your classpath.

As for the other modules, `jersey-media-json-processing` has also few properties that can affect the registration of `JsonProcessingFeature` (besides CommonProperties.FEATURE_AUTO_DISCOVERY_DISABLE and the like):

- CommonProperties.JSON_PROCESSING_FEATURE_DISABLE

- ServerProperties.JSON_PROCESSING_FEATURE_DISABLE

- ClientProperties.JSON_PROCESSING_FEATURE_DISABLE

To configure MessageBodyReader<T>s / MessageBodyWriter<T>s provided by JSON-P you can simply add values for supported properties into the Configuration instance (client/server). Currently supported are these properties:

- `JsonGenerator.PRETTY_PRINTING` ("`jakarta.json.stream.JsonGenerator.prettyPrinting`")

Example 9.12. Building client with JSON-Processing JSON feature enabled.

    ClientBuilder.newClient(new ClientConfig()
            // The line below that registers JSON-Processing feature can be
            // omitted if FEATURE_AUTO_DISCOVERY_DISABLE is not disabled.
            .register(JsonProcessingFeature.class)
            .property(JsonGenerator.PRETTY_PRINTING, true)
    );

Example 9.13. Creating JAX-RS application with JSON-Processing JSON feature enabled.

    // Create JAX-RS application.
    final Application application = new ResourceConfig()
            // The line below that registers JSON-Processing feature can be
            // omitted if FEATURE_AUTO_DISCOVERY_DISABLE is not disabled.
            .register(JsonProcessingFeature.class)
            .packages("org.glassfish.jersey.examples.jsonp")
            .property(JsonGenerator.PRETTY_PRINTING, true);

#### 9.1.3.3. Examples

Jersey provides a JSON Processing example on how to use JSON-Processing to consume/produce JSON.

### 9.1.4. Jackson (2.x)

#### 9.1.4.1. Dependency

To use Jackson 2.x as your JSON provider you need to add `jersey-media-json-jackson` module to your `pom.xml` file:

    <dependency>
        <groupId>org.glassfish.jersey.media</groupId>
        <artifactId>jersey-media-json-jackson</artifactId>
        <version>3.1.10</version>
    </dependency>

If you're not using Maven make sure to have all needed dependencies (see jersey-media-json-jackson) on the classpath.

#### 9.1.4.2. Configure and register

### Note

Note that namespace for Jackson 2.x is (`com.fasterxml.jackson`).

Jackson JSON processor could be controlled via providing a custom Jackson 2 ObjectMapper instance. This could be handy if you need to redefine the default Jackson behaviour and to fine-tune how your JSON data structures look like. Detailed description of all Jackson features is out of scope of this guide. The example below gives you a hint on how to wire your `ObjectMapper` instance into your Jersey application.

Since the 2.36 version of Jersey it is possible to filter (include/exclude) Jackson modules by properties CommonProperties.JSON_JACKSON_DISABLED_MODULES and CommonProperties.JSON_JACKSON_ENABLED_MODULES (with their client/server derivatives). If the CommonProperties.JSON_JACKSON_ENABLED_MODULES property is used, only those named modules will be used for JSON processing. On the other hand if the CommonProperties.JSON_JACKSON_DISABLED_MODULES property is used, those listed modules will be explicitly excluded from processing while other (not listed) will remain. Please note that the `JaxbAnnotationModule` module is always excluded from processing and this is not configurable.

In order to use Jackson as your JSON (JAXB/POJO) provider you need to register JacksonFeature and a `ContextResolver<T>` for `ObjectMapper`, if needed, in your Configurable (client/server).

Example 9.14. `ContextResolver<ObjectMapper>`

    @Provider
    public class MyObjectMapperProvider implements ContextResolver<ObjectMapper> {

        final ObjectMapper defaultObjectMapper;

        public MyObjectMapperProvider() {
            defaultObjectMapper = createDefaultMapper();
        }

        @Override
        public ObjectMapper getContext(Class<?> type) {
                return defaultObjectMapper;
            }
        }

        private static ObjectMapper createDefaultMapper() {
            final ObjectMapper result = new ObjectMapper();
            result.configure(Feature.INDENT_OUTPUT, true);

            return result;
        }

        // ...
    }

To view the complete example source code, see MyObjectMapperProvider class from the JSON-Jackson example.

Example 9.15. Building client with Jackson JSON feature enabled.

    final Client client = ClientBuilder.newBuilder()
            .register(MyObjectMapperProvider.class)  // No need to register this provider if no special configuration is required.
            .register(JacksonFeature.class)
            .build();

Example 9.16. Creating JAX-RS application with Jackson JSON feature enabled.

    // Create JAX-RS application.
    final Application application = new ResourceConfig()
            .packages("org.glassfish.jersey.examples.jackson")
            .register(MyObjectMapperProvider.class)  // No need to register this provider if no special configuration is required.
            .register(JacksonFeature.class);

#### 9.1.4.3. Examples

Jersey provides JSON Jackson (2.x) example showing how to use Jackson to consume/produce JSON.

### 9.1.5. Jettison

JAXB approach for (de)serializing JSON in Jettison module provides, in addition to using pure JAXB, configuration options that could be set on an JettisonConfig instance. The instance could be then further used to create a JettisonJaxbContext, which serves as a main configuration point in this area. To pass your specialized `JettisonJaxbContext` to Jersey, you will finally need to implement a JAXBContext ContextResolver<T> (see below).

#### 9.1.5.1. Dependency

To use Jettison as your JSON provider you need to add `jersey-media-json-jettison` module to your `pom.xml` file:

    <dependency>
        <groupId>org.glassfish.jersey.media</groupId>
        <artifactId>jersey-media-json-jettison</artifactId>
        <version>3.1.10</version>
    </dependency>

If you're not using Maven make sure to have all needed dependencies (see jersey-media-json-jettison) on the classpath.

#### 9.1.5.2. JSON Notations

`JettisonConfig` allows you to use two JSON notations. Each of these notations serializes JSON in a different way. Following is a list of supported notations:

- JETTISON_MAPPED (default notation)

- BADGERFISH

You might want to use one of these notations, when working with more complex XML documents. Namely when you deal with multiple XML namespaces in your JAXB beans.

Individual notations and their further configuration options are described below. Rather then explaining rules for mapping XML constructs into JSON, the notations will be described using a simple example. Following are JAXB beans, which will be used.

Example 9.17. JAXB beans for JSON supported notations description, simple address bean

    @XmlRootElement
    public class Address {
        public String street;
        public String town;

        public Address(){}

        public Address(String street, String town) {
            this.street = street;
            this.town = town;
        }
    }

Example 9.18. JAXB beans for JSON supported notations description, contact bean

    @XmlRootElement
    public class Contact {

        public int id;
        public String name;
        public List<Address> addresses;

        public Contact() {};

        public Contact(int id, String name, List<Address> addresses) {
            this.name = name;
            this.id = id;
            this.addresses =
                (addresses != null) ? new LinkedList<Address>(addresses) : null;
        }
    }

Following text will be mainly working with a contact bean initialized with:

Example 9.19. JAXB beans for JSON supported notations description, initialization

    Address[] addresses = {new Address("Long Street 1", "Short Village")};
    Contact contact = new Contact(2, "Bob", Arrays.asList(addresses));

I.e. contact bean with `id=2`, `name="Bob"` containing a single address (`street="Long Street 1"`, `town="Short Village"`).

All below described configuration options are documented also in api-docs at JettisonConfig.

##### 9.1.5.2.1. Jettison mapped notation

If you need to deal with various XML namespaces, you will find Jettison `mapped` notation pretty useful. Lets define a particular namespace for `id` item:

    ...
    @XmlElement(namespace="http://example.com")
    public int id;
    ...

Then you simply configure a mapping from XML namespace into JSON prefix as follows:

Example 9.20. XML namespace to JSON mapping configuration for Jettison based `mapped` notation

    Map<String,String> ns2json = new HashMap<String, String>();
    ns2json.put("http://example.com", "example");
    context = new JettisonJaxbContext(
        JettisonConfig.mappedJettison().xml2JsonNs(ns2json).build(),
        types);

Resulting JSON will look like in the example below.

Example 9.21. JSON expression with XML namespaces mapped into JSON

    {
       "contact":{
          "example.id":2,
          "name":"Bob",
          "addresses":{
             "street":"Long Street 1",
             "town":"Short Village"
          }
       }
    }

Please note, that `id` item became `example.id` based on the XML namespace mapping. If you have more XML namespaces in your XML, you will need to configure appropriate mapping for all of them.

Another configurable option introduced in Jersey version 2.2 is related to serialization of JSON arrays with Jettison's mapped notation. When serializing elements representing single item lists/arrays, you might want to utilise the following Jersey configuration method to explicitly name which elements to treat as arrays no matter what the actual content is.

Example 9.22. JSON Array configuration for Jettison based `mapped` notation

    context = new JettisonJaxbContext(
        JettisonConfig.mappedJettison().serializeAsArray("name").build(),
        types);

Resulting JSON will look like in the example below, unimportant lines removed for sanity.

Example 9.23. JSON expression with JSON arrays explicitly configured via Jersey

    {
       "contact":{
          ...
          "name":["Bob"],
          ...
       }
    }

##### 9.1.5.2.2. Badgerfish notation

From JSON and JavaScript perspective, this notation is definitely the worst readable one. You will probably not want to use it, unless you need to make sure your JAXB beans could be flawlessly written and read back to and from JSON, without bothering with any formatting configuration, namespaces, etc.

`JettisonConfig` instance using `badgerfish` notation could be built with

    JettisonConfig.badgerFish().build()

and the JSON output JSON will be as follows.

Example 9.24. JSON expression produced using `badgerfish` notation

    {
       "contact":{
          "id":{
             "$":"2"
          },
          "name":{
             "$":"Bob"
          },
          "addresses":{
             "street":{
                "$":"Long Street 1"
             },
             "town":{
                "$":"Short Village"
             }
          }
       }
    }

#### 9.1.5.3. Configure and register

In order to use Jettison as your JSON (JAXB/POJO) provider you need to register JettisonFeature and a `ContextResolver<T>` for `JAXBContext` (if needed) in your Configurable (client/server).

Example 9.25. `ContextResolver<ObjectMapper>`

    @Provider
    public class JaxbContextResolver implements ContextResolver<JAXBContext> {

        private final JAXBContext context;
        private final Set<Class<?>> types;
        private final Class<?>[] cTypes = {Flights.class, FlightType.class, AircraftType.class};

        public JaxbContextResolver() throws Exception {
            this.types = new HashSet<Class<?>>(Arrays.asList(cTypes));
            this.context = new JettisonJaxbContext(JettisonConfig.DEFAULT, cTypes);
        }

        @Override
        public JAXBContext getContext(Class<?> objectType) {
            return (types.contains(objectType)) ? context : null;
        }
    }

Example 9.26. Building client with Jettison JSON feature enabled.

    final Client client = ClientBuilder.newBuilder()
            .register(JaxbContextResolver.class)  // No need to register this provider if no special configuration is required.
            .register(JettisonFeature.class)
            .build();

Example 9.27. Creating JAX-RS application with Jettison JSON feature enabled.

    // Create JAX-RS application.
    final Application application = new ResourceConfig()
            .packages("org.glassfish.jersey.examples.jettison")
            .register(JaxbContextResolver.class)  // No need to register this provider if no special configuration is required.
            .register(JettisonFeature.class);

#### 9.1.5.4. Examples

Jersey provides an JSON Jettison example on how to use Jettison to consume/produce JSON.

### 9.1.6. `@JSONP` - JSON with Padding Support

Jersey provides out-of-the-box support for JSONP - JSON with padding. The following conditions has to be met to take advantage of this capability:

- Resource method, which should return wrapped JSON, needs to be annotated with @JSONP annotation.

- MessageBodyWriter<T> for `application/json` media type, which also accepts the return type of the resource method, needs to be registered (see JSON section of this chapter).

- User's request has to contain `Accept` header with one of the JavaScript media types defined (see below).

Acceptable media types compatible with `@JSONP` are: `application/javascript`, `application/x-javascript`, `application/ecmascript`, `text/javascript`, `text/x-javascript`, `text/ecmascript`, `text/jscript`.

Example 9.28. Simplest case of using `@JSONP`

    @GET
    @JSONP
    @Produces({"application/json", "application/javascript"})
    public JaxbBean getSimpleJSONP() {
        return new JaxbBean("jsonp");
    }

Assume that we have registered a JSON providers and that the `JaxbBean` looks like:

Example 9.29. JaxbBean for @JSONP example

    @XmlRootElement
    public class JaxbBean {

        private String value;

        public JaxbBean() {}

        public JaxbBean(final String value) {
            this.value = value;
        }

        public String getValue() {
            return value;
        }

        public void setValue(final String value) {
            this.value = value;
        }
    }

When you send a `GET` request with `Accept` header set to `application/javascript` you'll get a result entity that look like:

    callback({
        "value" : "jsonp",
    })

There are, of course, ways to configure wrapping method of the returned entity which defaults to `callback` as you can see in the previous example. `@JSONP` has two parameters that can be configured: `callback` and `queryParam`. `callback` stands for the name of the JavaScript callback function defined by the application. The second parameter, `queryParam`, defines the name of the query parameter holding the name of the callback function to be used (if present in the request). Value of `queryParam` defaults to `__callback` so even if you do not set the name of the query parameter yourself, client can always affect the result name of the wrapping JavaScript callback method.

### Note

`queryParam` value (if set) always takes precedence over `callback` value.

Lets modify our example a little bit:

Example 9.30. Example of `@JSONP` with configured parameters.

    @GET
    @Produces({"application/json", "application/javascript"})
    @JSONP(callback = "eval", queryParam = "jsonpCallback")
    public JaxbBean getSimpleJSONP() {
        return new JaxbBean("jsonp");
    }

And make two requests:

    curl -X GET http://localhost:8080/jsonp

will return

    eval({
        "value" : "jsonp",
    })

and the

    curl -X GET http://localhost:8080/jsonp?jsonpCallback=alert

will return

    alert({
        "value" : "jsonp",
    })

Example. You can take a look at a provided JSON with Padding example.

### 9.1.7. Java API for JSON Binding (JSON-B)

Jersey uses Yasson for JSON Binding (JSR-367) implementation.

#### 9.1.7.1. Dependency

To use JSON-B as your JSON provider you need to add `jersey-media-json-binding` module to your `pom.xml` file:

    <dependency>
        <groupId>org.glassfish.jersey.media</groupId>
        <artifactId>jersey-media-json-binding</artifactId>
        <version>3.1.10</version>
    </dependency>

If you're not using Maven make sure to have all needed dependencies (see jersey-media-json-binding) on the classpath.

#### 9.1.7.2. Configure and register

As stated in Section 4.3, “Auto-Discoverable Features” JSON-Binding media module is one of the modules where you don't need to explicitly register its `Feature`s (`JsonBindingFeature`) in your client/server Configurable as this feature is automatically discovered and registered when you add `jersey-media-json-binding` module to your classpath.

To use custom preconfigured JSON-B, it is simply possible to register a `ContextResolver<T>` for `Jsonb` in your Configurable (client/server) and configure JsonbConfig.

Example 9.31. `ContextResolver<Jsonb>`

    @Provider
    public class JsonbContextResolver implements ContextResolver<Jsonb> {

            @Override
            public Jsonb getContext(Class<?> type) {
                JsonbConfig config = new JsonbConfig();
                // configure JsonbConfig
                ...
                return JsonbBuilder.create(config);
            }
    }

Example 9.32. `Register the feature and ContextResolver<Jsonb>`

    ClientBuilder.newClient(new ClientConfig()
        // The line below that registers JSON-Binding feature can be
        // omitted if FEATURE_AUTO_DISCOVERY_DISABLE is not disabled.
        .register(JsonBindingFeature.class)
        .register(JsonbContextResolver.class)
    );

Example. You can take a look at a provided JSON-B example..

### 9.1.8. Properties for configuring JSON providers

Apart from using `ContextResolver<T>` for configuring directly the specific JSON provider classes, Jersey supports additional configuration properties prefixed by `JSON` that are available in Section A.6, “Jersey configuration properties for message & entity processing”

## 9.2. XML

As you probably already know, Jersey uses `MessageBodyWriter<T>`s and `MessageBodyReader<T>`s to parse incoming requests 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.

### 9.2.1. Low level XML support

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

Example 9.33. Low level XML test - methods added to `HelloWorldResource.java`

    @POST
    @Path("StreamSource")
    public StreamSource getStreamSource(StreamSource streamSource) {
        return streamSource;
    }

    @POST
    @Path("SAXSource")
    public SAXSource getSAXSource(SAXSource saxSource) {
        return saxSource;
    }

    @POST
    @Path("DOMSource")
    public DOMSource getDOMSource(DOMSource domSource) {
        return domSource;
    }

    @POST
    @Path("Document")
    public Document getDocument(Document document) {
        return document;
    }

Both `MessageBodyWriter<T>` and `MessageBodyReader<T>` are used in this case, all we need is a `POST` request with some XML document as a request entity. To keep this as simple as possible only root element with no content will be sent: `"<test />"`. You can create JAX-RS client to do that or use some other tool, for example `curl`:

    curl -v http://localhost:8080/base/helloworld/StreamSource -d "<test/>"

You should get exactly the 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.

### 9.2.2. Getting started with JAXB

Good start for people which already have some experience with JAXB annotations is JAXB example. You can see various use-cases 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 the right chapter.

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

Example 9.34. Planet class

    @XmlRootElement
    public class Planet {
        public int id;
        public String name;
        public double radius;
    }

Example 9.35. Resource class

    @Path("planet")
    public class Resource {

        @GET
        @Produces(MediaType.APPLICATION_XML)
        public Planet getPlanet() {
            final Planet planet = new Planet();

            planet.id = 1;
            planet.name = "Earth";
            planet.radius = 1.0;

            return planet;
        }
    }

You can see there is some extra annotation declared on `Planet` class, particularly @XmlRootElement. This is an JAXB annotation which maps java classes to XML elements. We don't need to specify anything else, because `Planet` is very simple class and all fields are public. In this case, XML element name will be derived from the class name or you can set the 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 JAX-RS client for making requests to this resource and this is easy as:

                        Planet planet = webTarget.path("planet").request(MediaType.APPLICATION_XML_TYPE).get(Planet.class);

There is pre-created `WebTarget` object which points to our applications context root and we simply add path (in our case 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.

Example 9.36. Method for consuming Planet

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

After valid request is made, service will print out string representation of `Planet`, which can look like `Planet{id=2, name='Mars', radius=1.51}`. With JAX-RS client you can do:

                        webTarget.path("planet").request().post(Entity.xml(planet));

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` which is XML to java compiler and it is part of JAXB.

### 9.2.3. 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 an @XmlRootElement annotation on `Planet` class.

Example 9.37. Resource class - JAXBElement

    @Path("planet")
    public class Resource {

        @GET
        @Produces(MediaType.APPLICATION_XML)
        public JAXBElement<Planet> getPlanet() {
            Planet planet = new Planet();

            planet.id = 1;
            planet.name = "Earth";
            planet.radius = 1.0;

            return new JAXBElement<Planet>(new QName("planet"), Planet.class, planet);
        }

        @POST
        @Consumes(MediaType.APPLICATION_XML)
        public void setPlanet(JAXBElement<Planet> planet) {
            System.out.println("setPlanet " + planet.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 complicated than server side because you can't do `JAXBElement<Planet>` so JAX-RS client API provides way how to workaround it by declaring subclass of `GenericType<T>`.

Example 9.38. Client side - JAXBElement

    // GET
    GenericType<JAXBElement<Planet>> planetType = new GenericType<JAXBElement<Planet>>() {};

    Planet planet = (Planet) webTarget.path("planet").request(MediaType.APPLICATION_XML_TYPE).get(planetType).getValue();
    System.out.println("### " + planet);

    // POST
    planet = new Planet();

    // ...

    webTarget.path("planet").post(new JAXBElement<Planet>(new QName("planet"), Planet.class, planet));

### 9.2.4. Using custom JAXBContext

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

Example 9.39. PlanetJAXBContextProvider

    @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 to reminder - you have to register them in the client config (client does not do anything like package scanning done by server).

Example 9.40. Using Provider with JAX-RS client

    ClientConfig config = new ClientConfig();
    config.register(PlanetJAXBContextProvider.class);

    Client client = ClientBuilder.newClient(config);

### 9.2.5. MOXy

If you want to use MOXy as your JAXB implementation instead of JAXB RI you have two options. You can either use the standard JAXB mechanisms to define the `JAXBContextFactory` from which a `JAXBContext` instance would be obtained (for more on this topic, read JavaDoc on JAXBContext) or you can add `jersey-media-moxy` module to your project and register/configure MoxyXmlFeature class/instance in the Configurable.

Example 9.41. Add `jersey-media-moxy` dependency.

    <dependency>
        <groupId>org.glassfish.jersey.media</groupId>
        <artifactId>jersey-media-moxy</artifactId>
        <version>3.1.10</version>
    </dependency>

Example 9.42. Register the `MoxyXmlFeature` class.

    final ResourceConfig config = new ResourceConfig()
        .packages("org.glassfish.jersey.examples.xmlmoxy")
        .register(MoxyXmlFeature.class);

Example 9.43. Configure and register an `MoxyXmlFeature` instance.

    // Configure Properties.
    final Map<String, Object> properties = new HashMap<String, Object>();
    // ...

    // Obtain a ClassLoader you want to use.
    final ClassLoader classLoader = Thread.currentThread().getContextClassLoader();

    final ResourceConfig config = new ResourceConfig()
        .packages("org.glassfish.jersey.examples.xmlmoxy")
        .register(new MoxyXmlFeature(
            properties,
            classLoader,
            true, // Flag to determine whether eclipselink-oxm.xml file should be used for lookup.
            CustomClassA.class, CustomClassB.class  // Classes to be bound.
        ));

### 9.2.6. Properties for configuring XML providers

Apart from using `ContextResolver<T>` for configuring directly the specific JSON provider classes, Jersey supports additional configuration properties prefixed by `JAXB` and `XML` that are available in Section A.6, “Jersey configuration properties for message & entity processing”

## 9.3. Multipart

### 9.3.1. Overview

The classes in this module provide an integration of `multipart/*` request and response bodies in a JAX-RS runtime environment. The set of registered providers is leveraged, in that the content type for a body part of such a message reuses the same `MessageBodyReader<T>`/`MessageBodyWriter<T>` implementations as would be used for that content type as a standalone entity.

The following list of general MIME MultiPart features is currently supported:

- The `MIME-Version: 1.0` HTTP header is included on generated responses. It is accepted, but not required, on processed requests.

- A MessageBodyReader<T> implementation for consuming MIME MultiPart entities.

- A `MessageBodyWriter<T>` implementation for producing MIME MultiPart entities. The appropriate `@Provider` is used to serialize each body part, based on its media type.

- Optional creation of an appropriate `boundary` parameter on a generated `Content-Type` header, if not already present.

For more information refer to Multi Part.

#### 9.3.1.1. Dependency

To use multipart features you need to add `jersey-media-multipart` module to your `pom.xml` file:

    <dependency>
        <groupId>org.glassfish.jersey.media</groupId>
        <artifactId>jersey-media-multipart</artifactId>
        <version>3.1.10</version>
    </dependency>

If you're not using Maven make sure to have all needed dependencies (see jersey-media-multipart) on the class-path.

#### 9.3.1.2. Registration

Prior to Jersey 3.1.0, before you can use the capabilities of the `jersey-media-multipart` module in your client/server code, you need to register MultiPartFeature. The multipart feature is supported by Jakarta RESTful Web Services 3.1 multipart API. From Jersey 3.1.0 on, the MultiPartFeature is no longer required to be registered and it is registered automatically.

#### 9.3.1.3. Examples

Jersey provides a Multipart Web Application Example on how to use multipart features.

### 9.3.2. Client

- Client using Jersey API

- Client using Jakarta REST API

#### 9.3.2.1. Client using Jersey API

MultiPart class (or it's subclasses) can be used as an entry point to use `jersey-media-multipart` module on the client side. This class represents a MIME multipart message and is able to hold an arbitrary number of BodyParts. Default media type is multipart/mixed for `MultiPart` entity and `text/plain` for `BodyPart`.

Example 9.44. `MultiPart` entity

    final MultiPart multiPartEntity = new MultiPart()
            .bodyPart(new BodyPart().entity("hello"))
            .bodyPart(new BodyPart(new JaxbBean("xml"), MediaType.APPLICATION_XML_TYPE))
            .bodyPart(new BodyPart(new JaxbBean("json"), MediaType.APPLICATION_JSON_TYPE));

    final WebTarget target = // Create WebTarget.
    final Response response = target
            .request()
            .post(Entity.entity(multiPartEntity, multiPartEntity.getMediaType()));

If you send a `multiPartEntity` to the server the entity with `Content-Type` header in HTTP message would look like:

Example 9.45. `MultiPart` entity in HTTP message.

    Content-Type: multipart/mixed; boundary=Boundary_1_829077776_1369128119878

    --Boundary_1_829077776_1369128119878
    Content-Type: text/plain

    hello
    --Boundary_1_829077776_1369128119878
    Content-Type: application/xml

    <?xml version="1.0" encoding="UTF-8" standalone="yes"?><jaxbBean><value>xml</value></jaxbBean>
    --Boundary_1_829077776_1369128119878
    Content-Type: application/json

    {"value":"json"}
    --Boundary_1_829077776_1369128119878--

When working with forms (e.g. media type `multipart/form-data`) and various fields in them, there is a more convenient class to be used - FormDataMultiPart. It automatically sets the media type for the `FormDataMultiPart` entity to `multipart/form-data` and `Content-Disposition` header to `FormDataBodyPart` body parts.

Example 9.46. `FormDataMultiPart` entity

    final FormDataMultiPart multipart = new FormDataMultiPart()
        .field("hello", "hello")
        .field("xml", new JaxbBean("xml"))
        .field("json", new JaxbBean("json"), MediaType.APPLICATION_JSON_TYPE);

    final WebTarget target = // Create WebTarget.
    final Response response = target.request().post(Entity.entity(multipart, multipart.getMediaType()));

To illustrate the difference when using `FormDataMultiPart` instead of `FormDataBodyPart` you can take a look at the `FormDataMultiPart` entity from HTML message:

Example 9.47. `FormDataMultiPart` entity in HTTP message.

    Content-Type: multipart/form-data; boundary=Boundary_1_511262261_1369143433608

    --Boundary_1_511262261_1369143433608
    Content-Type: text/plain
    Content-Disposition: form-data; name="hello"

    hello
    --Boundary_1_511262261_1369143433608
    Content-Type: application/xml
    Content-Disposition: form-data; name="xml"

    <?xml version="1.0" encoding="UTF-8" standalone="yes"?><jaxbBean><value>xml</value></jaxbBean>
    --Boundary_1_511262261_1369143433608
    Content-Type: application/json
    Content-Disposition: form-data; name="json"

    {"value":"json"}
    --Boundary_1_511262261_1369143433608--

A common use-case for many users is sending files from client to server. For this purpose you can use classes from `org.glassfish.jersey.jersey.media.multipart` package, such as FileDataBodyPart or StreamDataBodyPart.

Example 9.48. Multipart - sending files.

    // MediaType of the body part will be derived from the file.
    final FileDataBodyPart filePart = new FileDataBodyPart("my_pom", new File("pom.xml"));

    final FormDataMultiPart multipart = new FormDataMultiPart()
        .field("foo", "bar")
        .bodyPart(filePart);

    final WebTarget target = // Create WebTarget.
    final Response response = target.request()
        .post(Entity.entity(multipart, multipart.getMediaType()));

### Warning

Do not use `ApacheConnectorProvider` nor `GrizzlyConnectorProvider` neither `JettyConnectorProvider` connector implementations with Jersey Multipart features. See Header modification issue warning for more details.

#### 9.3.2.2. Client using Jakarta REST API

EntityPart interface can be used as an entry point to use `jersey-media-multipart` module on the client side. This class represents multipart message is able to hold an arbitrary number of EntityParts. Default media type is multipart/form-data.

Example 9.49. Using `EntityPart.Builder` for building an Entity

    final List<EntityPart> multiPartEntity = new List<>();
    list.add(EntityPart.withName("part-01").content("hello").build());
    list.add(EntityPart.withName("part-01").content(new JaxbBean("xml")).mediaType(MediaType.APPLICATION_XML_TYPE).build()); //same name
    list.add(EntityPart.withName("part-02").content(new JaxbBean("json")).mediaType(MediaType.APPLICATION_JSON_TYPE).build()); //other name
    final GenericEntity<List<EntityPart>> genericEntity = new GenericEntity<>(list) {};
    final Entity entity = Entity.entity(genericEntity, MediaType.MULTIPART_FORM_DATA_TYPE);

    final WebTarget target = // Create WebTarget.
    final Response response = target.request().post(entity);

The common use-case for many users is sending files from client to server. It is also covered by EntityPart.Builder.

Example 9.50. EntityPart - sending files.

    // MediaType of the body part will be derived from the file.
    final List<EntityPart> multiPartEntity = new List<>();
    list.add(EntityPart.withFileName("file001.txt").content(Files.newInputStream(Path.of("file001.txt"))).build());
    list.add(EntityPart.withFileName("mypom.xml").content(Files.newInputStream(Path.of("pom.xml"))).build());

    final GenericEntity<List<EntityPart>> genericEntity = new GenericEntity<>(list) {};
    final Entity entity = Entity.entity(genericEntity, MediaType.MULTIPART_FORM_DATA_TYPE);

    final WebTarget target = // Create WebTarget.
    final Response response = target.request().post(entity);

### 9.3.3. Server

- Server using Jersey API

- Server using Jakarta REST API

#### 9.3.3.1. Jersey Server API

Returning a multipart response from server to client is not much different from the parts described in the client section above. To obtain a multipart entity, sent by a client, in the application you can use two approaches:

- Injecting the whole MultiPart entity.

- Injecting particular parts of a `form-data` multipart request via @FormDataParam annotation.

##### 9.3.3.1.1. Injecting and returning the `MultiPart` entity

Working with `MultiPart` types is no different from injecting/returning other entity types. Jersey provides `MessageBodyReader<T>` for reading the request entity and injecting this entity into a method parameter of a resource method and `MessageBodyWriter<T>` for writing output entities. You can expect that either `MultiPart` or `FormDataMultiPart` (`multipart/form-data` media type) object to be injected into a resource method.

Example 9.51. Resource method using `MultiPart` as input parameter / return value.

    @POST
    @Produces("multipart/mixed")
    public MultiPart post(final FormDataMultiPart multiPart) {
        return multiPart;
    }

##### 9.3.3.1.2. Injecting with `@FormDataParam`

If you just need to bind the named body part(s) of a `multipart/form-data` request entity body to a resource method parameter you can use @FormDataParam annotation.

This annotation in conjunction with the media type `multipart/form-data` should be used for submitting and consuming forms that contain files, non-ASCII data, and binary data.

The type of the annotated parameter can be one of the following (for more detailed description see javadoc to @FormDataParam):

- `FormDataBodyPart` - The value of the parameter will be the first named body part or `null` if such a named body part is not present.

- A `List` or `Collection` of `FormDataBodyPart`. The value of the parameter will be one or more named body parts with the same name or `null` if such a named body part is not present.

- `FormDataContentDisposition` - The value of the parameter will be the content disposition of the first named body part part or `null` if such a named body part is not present.

- A `List` or `Collection` of `FormDataContentDisposition`. The value of the parameter will be one or more content dispositions of the named body parts with the same name or `null` if such a named body part is not present.

- A type for which a message body reader is available given the media type of the first named body part. The value of the parameter will be the result of reading using the message body reader given the type `T`, the media type of the named part, and the bytes of the named body part as input.

  If there is no named part present and there is a default value present as declared by @DefaultValue then the media type will be set to `text/plain`. The value of the parameter will be the result of reading using the message body reader given the type `T`, the media type `text/plain`, and the UTF-8 encoded bytes of the default value as input.

  If there is no message body reader available and the type `T` conforms to a type specified by @FormParam then processing is performed as specified by `@FormParam`, where the values of the form parameter are `String` instances produced by reading the bytes of the named body parts utilizing a message body reader for the `String` type and the media type `text/plain`.

  If there is no named part present then processing is performed as specified by `@FormParam`.

Example 9.52. Use of `@FormDataParam` annotation

    @POST
    @Consumes(MediaType.MULTIPART_FORM_DATA)
    public String postForm(
        @DefaultValue("true") @FormDataParam("enabled") boolean enabled,
        @FormDataParam("data") FileData bean,
        @FormDataParam("file") InputStream file,
        @FormDataParam("file") FormDataContentDisposition fileDisposition) {

        // ...
    }

In the example above the server consumes a `multipart/form-data` request entity body that contains one optional named body part `enabled` and two required named body parts `data` and `file`.

The optional part `enabled` is processed as a `boolean` value, if the part is absent then the value will be `true`.

The part `data` is processed as a JAXB bean and contains some meta-data about the following part.

The part `file` is a file that is uploaded, this is processed as an `InputStream`. Additional information about the file from the `Content-Disposition` header can be accessed by the parameter `fileDisposition`.

### Tip

`@FormDataParam` annotation can be also used on fields.

#### 9.3.3.2. Properties for configuring the Multipart

There are multiple options that can be used when configuring the multipart. See MultiPartProperties or Section A.15, “Multipart configuration properties” for the possibilities.

The options can set in a configuration file specified by the MultiPartProperties.MULTI_PART_CONFIG_RESOURCE property. That is the standard Java properties file.

Or the options can be set programmatically, by registering `ContextResolver<MultiPartProperties>`. For instance:

    ResourceConfig resourceConfig = new ResourceConfig();
    resourceConfig.register(new MultiPartProperties().bufferThreshold(65535).maxParts(2).resolver());

#### 9.3.3.3. Server using Jakarta REST API

Using EntityPart on the server side is similar to the client side. Jakarta REST specification allows for returning a `Response` or a `List` of `EntityPart`s.

Receiving the EntityParts can be done either using `@FormParam` annotations and `EntityPart`, `InputStream` or `String` data-types, or using a `List` of `EntityPart`s.

Example 9.53. Use of `@FormParam` annotation with `EntityPart` `InputStream` and `String` types and returning a `Response`

    @POST
    @Path("/postFormVarious")
    public Response postFormVarious(@FormParam("name1") EntityPart part1,
                    @FormParam("name2") InputStream part2,
                    @FormParam("name3") String part3) throws IOException {
        final List<EntityPart> list = new LinkedList<>();
        list.add(EntityPart.withName(part1.getName())
            .content(part1.getContent(String.class) + new String(part2.readAllBytes()) + part3)
            .mediaType(MediaType.TEXT_PLAIN_TYPE)
            .build());
        final GenericEntity<List<EntityPart>> genericEntity = new GenericEntity<>(list) {};
        return Response.ok(genericEntity, MediaType.MULTIPART_FORM_DATA_TYPE).build();
    }

Example 9.54. Receiving a `List` of `EntityPart`s

    @POST
    @Path("/postListForm")
    public String postEntityPartForm(@FormParam("part-0x") List<EntityPart> part) throws IOException {
        final String entity = part.get(0).getContent(String.class) + part.get(1).getContent(String.class);
        return entity;
    }

Example 9.55. Returning a `List` of `EntityPart`s

    @GET
    @Produces(MediaType.MULTIPART_FORM_DATA)
    @Path("/getList")
    public List<EntityPart> getList() throws IOException {
        final List<EntityPart> list = new LinkedList<>();
        list.add(EntityPart.withName("name1").content("data1").build());
        return list;
    }

Prev |  | Next
Chapter 8. JAX-RS Entity Providers | Home | Chapter 10. Filters and Interceptors