Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

MediaType.APPLICATION_XML and MediaType.APPLICATION_JSON in a Jersey demo application

Once I got this Question Latest Jersey example does not work answered, I run into another curious problem:

The server, GET methods work fine. I tested and added some test code for helloworld-pure-jax-rs example, and esp. added a POST request for JSON:

package org.glassfish.jersey.examples.helloworld.jaxrs;

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


@Path("helloworld")
public class HelloWorldResource
{
    public static final String  CLICHED_MESSAGE = "Hello World!";

    @GET
    @Produces(MediaType.TEXT_PLAIN)
    public String getHello()
    {
        return CLICHED_MESSAGE;
    }

    @GET
    @Produces(MediaType.APPLICATION_JSON)
    public String getHelloJson()
    {
        return "{ \"message\":" + CLICHED_MESSAGE + "}";
    }

    @GET
    @Produces(MediaType.TEXT_HTML)
    public String getHelloHtml()
    {
        return "<html> " + "<title>" + "Hello Jersey" + "</title>" + "<body><h1>" + CLICHED_MESSAGE
                + "</body></h1>" + "</html> ";
    }

    @GET
    @Produces(MediaType.TEXT_PLAIN)
    @Path("/v2")
    public String getHello2()
    {
        return CLICHED_MESSAGE + " v2";
    }

    @GET
    @Produces(MediaType.TEXT_PLAIN)
    @Path("/{id}")
    public String getHelloId(@PathParam("id") String id)
    {
        return CLICHED_MESSAGE + " Parameter: " + id;
    }

    @GET
    @Produces(MediaType.TEXT_PLAIN)
    @Path("/id/{id : [a-zA-Z][a-zA-Z_0-9]}")
    public String getHelloIdId(@PathParam("id") String id)
    {
        return CLICHED_MESSAGE + " Parameter: " + id;
    }

    @POST
    @Consumes(MediaType.TEXT_PLAIN)
    @Produces(MediaType.TEXT_PLAIN)
    public Response test(String test)
    {
        if (test.equals("test"))
            return Response.status(400).entity("Error: " + test).build();
        return Response.status(200).entity(test).build();
    }

    @POST
    @Path("/test")
    @Consumes(MediaType.APPLICATION_JSON)
    @Produces(MediaType.APPLICATION_JSON)
    public Response testJSON(Test test)
    {
        String result = "Test JSON created : " + test.getName() + "" + test.getAge();
        // return result;
        return Response.status(200).entity(result).build();
    }

    @POST
    @Path("/test")
    @Consumes(MediaType.APPLICATION_XML)
    @Produces(MediaType.APPLICATION_XML)
    public Response testXML(Test test)
    {
        String result = "Test XML created : " + test.getName() + "" + test.getAge();
        // return result;
        return Response.status(200).entity(result).build();
    }

}

Here ist the rest of the classes:

package org.glassfish.jersey.examples.helloworld.jaxrs;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.URI;

import javax.ws.rs.core.UriBuilder;
import javax.ws.rs.ext.RuntimeDelegate;

import com.sun.net.httpserver.HttpHandler;
import com.sun.net.httpserver.HttpServer;

/**
 * Hello world application using only the standard JAX-RS API and lightweight
 * HTTP server bundled in JDK.
 *
 * @author Martin Matula (martin.matula at oracle.com)
 */
@SuppressWarnings("restriction")
public class App
{

    /**
     * Starts the lightweight HTTP server serving the JAX-RS application.
     *
     * @return new instance of the lightweight HTTP server
     * @throws IOException
     */
    static HttpServer startServer() throws IOException
    {
        // create a new server listening at port 8080
        HttpServer server = HttpServer.create(new InetSocketAddress(getBaseURI().getPort()), 0);

        // create a handler wrapping the JAX-RS application
        HttpHandler handler = RuntimeDelegate.getInstance().createEndpoint(new JaxRsApplication(),
                HttpHandler.class);

        // map JAX-RS handler to the server root
        server.createContext(getBaseURI().getPath(), handler);

        // start the server
        server.start();

        return server;
    }

    public static void main(String[] args) throws IOException
    {
        System.out.println("\"Hello World\" Jersey Example Application");

        HttpServer server = startServer();

        System.out.println("Application started.\n" + "Try accessing " + getBaseURI()
                + "helloworld in the browser.\n" + "Hit enter to stop the application...");
        System.in.read();
        server.stop(0);
    }

    private static int getPort(int defaultPort)
    {
        final String port = System.getProperty("jersey.config.test.container.port");
        if (null != port)
        {
            try
            {
                return Integer.parseInt(port);
            }
            catch (NumberFormatException e)
            {
                System.out.println("Value of jersey.config.test.container.port property"
                        + " is not a valid positive integer [" + port + "]."
                        + " Reverting to default [" + defaultPort + "].");
            }
        }
        return defaultPort;
    }

    /**
     * Gets base {@link URI}.
     *
     * @return base {@link URI}.
     */
    public static URI getBaseURI()
    {
        return UriBuilder.fromUri("http://localhost/").port(getPort(8080)).build();
    }
}


public class Test
{
    public int      age     = 0;
    public String   name    = "";

    /**
     * 
     */
    public Test()
    {
        super();
    }

    /**
     * @param age
     */
    public Test(int age)
    {
        super();
        this.age = age;
    }

    /**
     * @param name
     */
    public Test(String name)
    {
        super();
        this.name = name;
    }

    /**
     * @param name
     * @param age
     */
    public Test(String name, int age)
    {
        super();
        this.name = name;
        this.age = age;
    }

    public int getAge()
    {
        return age;
    }

    public String getName()
    {
        return name;
    }

    public void setAge(int age)
    {
        this.age = age;
    }

    public void setName(String name)
    {
        this.name = name;
    }
}

package org.glassfish.jersey.examples.helloworld.jaxrs;

import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
import javax.ws.rs.core.Application;

public class JaxRsApplication extends Application
{
    private final Set<Class<?>> classes;

    public JaxRsApplication()
    {
        HashSet<Class<?>> c = new HashSet<Class<?>>();
        c.add(HelloWorldResource.class);
        classes = Collections.unmodifiableSet(c);
    }

    @Override
    public Set<Class<?>> getClasses()
    {
        return classes;
    }
}

This works fine for the plain text post message, but fpr the json (MediaType.APPLICATION_JSON )and xml part (MediaType.APPLICATION_XML) it fails stating not a supported media type. Any idea what could be wrong?

like image 234
user2737950 Avatar asked Nov 02 '14 07:11

user2737950


1 Answers

JAX-RS has a bunch of built-in handlers that can marshal to and from a few different specific Java types.

Once we start dealing with custom data-binding (marshalling/unmarshalling to Java objects), we are in a different ball game. We now require some other MessageBodyWriters and MesageBodyReaders.

Fortunately, there are already readers and writers available for XML and JSON data-binding. JAX-RS comes with a standard XML marshalling/unmarshalling, with one caveat.. we must use JAXB annotations. So for your Test class, assuming it's like this

public class Test {
    private String name;
    private int age;

    public String getName() { return name; }
    public void setName(String name) { this.name = name;}
    public int getAge() { return age; }
    public void setAge(int age) { this.age = age; }  
}

to make allow the JAXB provider to unmarshall/marshall, we should provide, at minimum, an @XmlRootElement

@XmlRootElement
public class Test {
   ....
}

Doing this should allow the XML to work.

As far as the JSON, JSON binding is not a standard par of the specification, but we can simply add a dependency to the project, that will automatically register the needed provider to handle JSON binding. You can look at the pom.xml for the json-moxy example. You will see this needed dependency

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

What the dependency allows application to do, is marshal/unmarshal jSON to/from our Java objects, using the JAXB annotations. So just by adding this dependency to the pom.xml. The application should work. Just tested.

like image 148
Paul Samsotha Avatar answered Sep 28 '22 07:09

Paul Samsotha