I get the following exception when I execute the REST Client :
InboundJaxrsResponse{ClientResponse{method=GET, uri=http://localhost:8080/com.dcr.jersey.first/webapi/todo, status=406, reason=Not Acceptable}}
Exception in thread "main" javax.ws.rs.NotAcceptableException: HTTP 406 Not Acceptable
On web browser( when tomcat is running), the URL : http://localhost:8080/com.dcr.jersey.first/webapi/todo gives output
todo>
<description>This is my first todo - Description</description>
<summary>This is my first todo - Summary</summary>
</todo>
But running the client code throws the exception, what is the mapping that's missing here?, appreciate your guidance( included all code samples)
Here is the 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">
<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.dcr.jersey</param-value> -->
<!-- <param-value>com.dcr.jersey.first</param-value> -->
<param-value>com.dcr.jersey.jaxb.model</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>
Here is the TodoResourceCliient executed:
package com.dcr.jersey.client;
import java.net.URI;
import javax.ws.rs.client.Client;
import javax.ws.rs.client.ClientBuilder;
import javax.ws.rs.client.WebTarget;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriBuilder;
import org.glassfish.jersey.client.ClientConfig;
public class TodoResourceCliient {
public static void main(String[] args) {
ClientConfig config = new ClientConfig();
Client client = ClientBuilder.newClient(config);
WebTarget target = client.target(getBaseURI());
System.out.println(target.path("webapi").path("todo").request()
.accept(MediaType.TEXT_PLAIN).get(Response.class)
.toString());
System.out.println(target.path("webapi").path("todo").request()
.accept(MediaType.TEXT_HTML).get(String.class));
System.out.println(target.path("webapi").path("todo").request()
.accept(MediaType.TEXT_XML).get(String.class));
System.out.println(target.path("webapi").path("todo").request()
.accept(MediaType.TEXT_PLAIN).get(String.class));
System.out.println(target.path("webapi").path("todo").request()
.accept(MediaType.APPLICATION_JSON).get(String.class));
}
private static URI getBaseURI() {
return UriBuilder.fromUri("http://localhost:8080/com.dcr.jersey.first").build();
}
}
TodoResource.java:
package com.dcr.jersey.jaxb.model;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
#Path("/todo")
public class TodoResource {
#GET
#Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
public Todo getXML() {
Todo todo = new Todo();
todo.setSummary("This is my first todo - Summary\n");
todo.setDescription("This is my first todo - Description\n");
return todo;
}
// This can be used to test the integration with the browser
#GET
#Produces({ MediaType.TEXT_XML,MediaType.TEXT_PLAIN,MediaType.TEXT_HTML})
public Todo getHTML() {
Todo todo = new Todo();
todo.setSummary("This is my first todo - Summary\n");
todo.setDescription("This is my first todo - Description\n");
return todo;
}
}
Todo.java:
package com.dcr.jersey.jaxb.model;
import javax.xml.bind.annotation.XmlRootElement;
#XmlRootElement
public class Todo {
private String summary;
private String description;
public String getSummary() {
return summary;
}
public void setSummary(String summary) {
this.summary = summary;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
}
Stacktrace from Console :
InboundJaxrsResponse{ClientResponse{method=GET, uri=http://localhost:8080/com.dcr.jersey.first/webapi/todo, status=500, reason=Internal Server Error}}
Exception in thread "main" javax.ws.rs.InternalServerErrorException: HTTP 500 Internal Server Error
at org.glassfish.jersey.client.JerseyInvocation.convertToException(JerseyInvocation.java:1002)
at org.glassfish.jersey.client.JerseyInvocation.translate(JerseyInvocation.java:799)
at org.glassfish.jersey.client.JerseyInvocation.access$500(JerseyInvocation.java:91)
at org.glassfish.jersey.client.JerseyInvocation$2.call(JerseyInvocation.java:687)
at org.glassfish.jersey.internal.Errors.process(Errors.java:315)
at org.glassfish.jersey.internal.Errors.process(Errors.java:297)
at org.glassfish.jersey.internal.Errors.process(Errors.java:228)
at org.glassfish.jersey.process.internal.RequestScope.runInScope(RequestScope.java:444)
at org.glassfish.jersey.client.JerseyInvocation.invoke(JerseyInvocation.java:683)
at org.glassfish.jersey.client.JerseyInvocation$Builder.method(JerseyInvocation.java:411)
at org.glassfish.jersey.client.JerseyInvocation$Builder.get(JerseyInvocation.java:307)
at com.dcr.jersey.client.TodoResourceCliient.main(TodoResourceCliient.java:27)
Dependencies included from pom.xml: am I missing any dependencies ?
<dependencies>
<dependency>
<groupId>org.glassfish.jersey.containers</groupId>
<artifactId>jersey-container-servlet-core</artifactId>
<!-- use the following artifactId if you don't need servlet 2.x compatibility -->
<!-- artifactId>jersey-container-servlet</artifactId -->
</dependency>
<!-- JSON support -->
<dependency>
<groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-media-moxy</artifactId>
</dependency>
</dependencies>
See Http Status Codes
406 Not Acceptable
The resource identified by the request is only capable of generating response entities which have content characteristics not acceptable according to the accept headers sent in the request.
The .accept(mediatype) is what set the Accept header for the request. You currently have five requests, each accepting a different type
MediaType.TEXT_PLAIN,MediaType.TEXT_HTML, MediaType.TEXT_XML, MediaType.TEXT_PLAIN, MediaType.APPLICATION_JSON
This is Content-Negotiation at work. The server side configuration of this is with the use of the #Produces (which goes in hand with the Accept header) and #Consumes(which goes in hand with the Content-Type header).
That being said, look at all your #Produces annotations. You currently only support the producing of media types
MediaType.APPLICATION_XML, MediaType.TEXT_XML, MediaType.APPLICATION_JSON
The missing ones are in bold above. Remove those, and given all else is correct, this should work for you.
Check your content type!
Setting to .accept(MediaType.TEXT_PLAIN) worked for me.
As correctly stated by peeskillet, your client calls with accept(MediaType.TEXT_PLAIN) and accept(MediaType.TEXT_HTML) will cause issues since your TodoResource methods do not specify these media types in the #Produces annotation.
Either
change your TodoResource class to support these media types
change your client code to remove the calls corresponding to these media types
Related
I am new to the restful webservices. I am new creating restful webservice in java using jersey . This webservice is getting data from mysql database and should display the response in xml..
But i am always getting the response error 500 from apache tomcat 7. In the console no error or exception is shown except the println method is diplaying the strings passed to it..but server is giving 500 error.. Please help me
userData.java
package com.userdb;
import javax.xml.bind.annotation.XmlRootElement;
#XmlRootElement
public class userData {
public String name;
public int iduser;
public userData(){}
public userData(String name, int iduser) {
this.name = name;
this.iduser = iduser;
}
public String getName() {
return name;
}
public int getIduser() {
return iduser;
}
public void setName(String name) {
this.name = name;
}
public void setIduser(int iduser) {
this.iduser = iduser;
}
}
airtime.java
package com.userdb;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.ArrayList;
import java.util.List;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
#Path("/resttest")
public class airtime {
ResultSet rs=null;
String msg="hello";
Connection con=null;
#GET
#Produces(MediaType.APPLICATION_XML)
#Path("/get_users")
public List<userData> get_users(){
List<userData> retUser=new ArrayList<>();
try {
Class.forName("com.mysql.jdbc.Driver").newInstance();
con=DriverManager.getConnection("jdbc:mysql://localhost:3306/mydb", "root", "");
System.out.println("DriveManager");
PreparedStatement ps=con.prepareStatement("SELECT * FROM users");
rs=ps.executeQuery();
System.out.println(rs);
while(rs.next()){
userData obj=new userData();
obj.setIduser(rs.getInt("iduser"));
obj.setName(rs.getString("name"));
retUser.add(obj);
System.out.println("userData obj added to list");
}
con.close();
} catch (Exception e){
e.printStackTrace();
}
return retUser;
}
}
web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" id="WebApp_ID" version="3.0">
<display-name>userdb</display-name>
<servlet>
<servlet-name>Jersey WebService</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.userdb</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>Jersey WebService</servlet-name>
<url-pattern>/api/*</url-pattern>
</servlet-mapping>
</web-app>
Solution 1:
Adjust the top of userData.java to contain the following lines at the top your file:
package com.userdb;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlAccessType;
#XmlAccessorType(XmlAccessType.FIELD)
#XmlRootElement
public class userData
{...}
Explanation: You will notice that an XmlAccessorType annotation and an XMLAccessType has been added. This configuration is required when using setters in your object. You will notice that adjusting the code to not use setters (with the above excluded) will also allow you to view your RESTful service in a browser.
Solution 2:
A quicker alternative, is to set your public variables name and iduser to private. This will also avoid the clash when mapping to xml.
There should be a warning something like "...messagebodywriter not found for media type=application/xml ...".
The possible cause may be that you didn't include this dependency.
<dependency>
<groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-media-jaxb</artifactId>
<version>2.21.1</version>
</dependency>
this is my workable pom dependencies
<dependencies>
<!-- jersey dependency -->
<dependency>
<groupId>org.glassfish.jersey.bundles</groupId>
<artifactId>jaxrs-ri</artifactId>
<version>2.21.1</version>
</dependency>
<!-- make jersey auto marshel to json -->
<dependency>
<groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-media-json-jackson</artifactId>
<version>2.21.1</version>
</dependency>
<!-- make jersey auto marshel to xml -->
<dependency>
<groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-media-jaxb</artifactId>
<version>2.21.1</version>
</dependency>
<dependency>
<groupId>org.codehaus.woodstox</groupId>
<artifactId>stax2-api</artifactId>
<version>3.1.4</version>
</dependency>
</dependencies>
a workable web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/javaee"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
version="3.0">
<display-name>Rest</display-name>
<servlet>
<servlet-name>MyApplication</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.blithe.resource</param-value>
</init-param>
<init-param>
<param-name>jersey.config.server.provider.scanning.recursive</param-name>
<param-value>true</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>MyApplication</servlet-name>
<url-pattern>/services/*</url-pattern>
</servlet-mapping>
</web-app>
workable resource
package com.blithe.resource;
import java.util.ArrayList;
import java.util.List;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import com.blithe.model.User;
#Path("helloworld")
public class HelloWorldResource
{
#GET
#Produces(MediaType.APPLICATION_XML)
public List<User> getStringArray(){
List<User> list = new ArrayList<>();
User u = new User();
u.setName("testName");
list.add(u);
return list;
}
}
and the model
package com.blithe.model;
import javax.xml.bind.annotation.XmlRootElement;
#XmlRootElement
public class User {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
Hope this will help you.
By the way, it is better not to include too many dependencies which might duplicate in your pom.xml, since some of them might conflict to each other. And it will cost a lot of time on debugging. So it's better to find out what dependencies are really needed.
Cheers!
Gregory Nikitas is right. The issue in your model class should also be taken care of.
im trying to create a jersey client to upload files. I have a web serice and a client. But i get everytime a 415 - unsupported Media Type and i don't know what the problem could be.
I`ve searched the i-net / stackoverflow but i cant find a proper solution for my problem. I tried many solutions but without success. You can see this as comments in my code.
Client:
private static void clientFileUpload() throws IOException {
ClientConfig config = new ClientConfig();
Client client = ClientBuilder.newClient(config);
client.register(MultiPartFeature.class);
URI baseUri = UriBuilder.fromUri("http://localhost:8080/vogella.jersey.first").build();
final WebTarget target = client.target(baseUri);
final FileDataBodyPart filepart = new FileDataBodyPart("files", new File("C:/Users/admin/Downloads/testtext.txt"));
final FormDataMultiPart formDataMultiPart = new FormDataMultiPart();
final FormDataMultiPart multiPart = (FormDataMultiPart) formDataMultiPart.field("foo", "bar").bodyPart(filepart);
multiPart.setMediaType(MediaType.MULTIPART_FORM_DATA_TYPE);
Response response = target.path("rest").path("hello").path("upload")
.request()
.header("Content-Type", MediaType.MULTIPART_FORM_DATA)
.post(Entity.entity(multiPart, multiPart.getMediaType()));
//.header("Content-Type", "multipart/form-data"
//.header("Content-Type", "multipart/form-data;charset=UTF-8")
//multiPart.getMediaType()
//"Content-Tpye: multipart/form-data"
System.out.println("--> " + response.getMediaType());
System.out.println("--> " + response.getStringHeaders());
System.out.println(":: RESPONSE : " + response);
System.out.println(":: STATUSCODE: " + response.getStatus() + " -- Reason: " + response.getStatusInfo());
String output = response.readEntity(String.class);
System.out.println(":: OUTPUT: " + output);
}
WebService:
I tried 2 different solutions but i can't find my mistake.
package vogella.jersey.first;
import java.io.File;
import javax.ws.rs.Consumes;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import org.glassfish.jersey.media.multipart.FormDataMultiPart;
import org.glassfish.jersey.media.multipart.MultiPart;
import org.glassfish.jersey.server.ResourceConfig;
#Path("/hello")
public class Hello {
#GET
#Path("/test")
#Produces("application/xml")
public MyBean getBean() {
return new MyBean("Hello MyBean", 42);
}
#POST
#Path("/test")
#Consumes("application/xml")
public String postMyBean(MyBean myBean) {
return myBean.anyString;
}
#POST
#Path("/upload")
#Consumes(MediaType.MULTIPART_FORM_DATA)
//#Produces("multipart/mixed")
public MultiPart post (final FormDataMultiPart multiPart) {
System.out.println("::: THIS IS THE MULTIPART MESSAGE: " + multiPart);
return multiPart;
}
#POST
#Path("/ul")
#Consumes(MediaType.MULTIPART_FORM_DATA)
#Produces("text/plain")
public Response uploadFile(final FormDataMultiPart form) {
String output = "Done";
return Response.status(200).entity(output).build();
}
}
Jersey REST files
Im able to send normal GET and Post Request to the server. But i need to send files too. I hope, someone can help me.
This is my web.xml:
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" id="WebApp_ID" version="3.0">
<display-name>vogella.jersey.first</display-name>
<servlet>
<servlet-name>Jersey REST Service</servlet-name>
<servlet-
class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
<!-- Register resources and providers under com.vogella.jersey.first package. -->
<init-param>
<param-name>jersey.config.server.provider.packages</param-name>
<param-value>vogella.jersey.first</param-value>
</init-param>
<!--
<init-param>
<param-name>jersey.config.server.provider.classnames</param-name>
<param-value>org.glassfish.jersey.media.multipart.MultiPartFeature</param-value>
</init-param>
-->
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>Jersey REST Service</servlet-name>
<url-pattern>/rest/*</url-pattern>
</servlet-mapping>
</web-app>
I want to use jersey framework. I´m running a web Service, using an ant app, on Java EE7. My application server is Glassfish
My method look like this:
package mypackage.service;
...
import org.glassfish.jersey.media.multipart.FormDataContentDisposition;
import org.glassfish.jersey.media.multipart.FormDataParam;
#POST
#Path("createSomething")
#Consumes(MULTIPART_FORM_DATA)
#Produces(APPLICATION_XML)
public Response createSomething(#FormDataParam("upload") InputStream is, #FormDataParam("upload") FormDataContentDisposition formData, #QueryParam("some") String some, #Context HttpServletRequest request) {
String fileLocation = "C:\\UploadFile\\" + formData.getFileName();
//more things, do not matter
try {
ctrl.saveFile(is, fileLocation);
String result = "Successfully File Uploaded on the path " + fileLocation;
return Response.status(Response.Status.OK).entity(result).build();
} catch (IOException e) {
e.printStackTrace();
return Response.status(Response.Status.INTERNAL_SERVER_ERROR).build();
}
I also have an application config:
package mypackage.service;
import java.util.HashSet;
import java.util.Set;
import javax.ws.rs.core.Application;
import org.glassfish.jersey.media.multipart.MultiPartFeature;
#javax.ws.rs.ApplicationPath("")
public class ApplicationConfig extends Application {
#Override
public Set<Class<?>> getClasses() {
final Set<Class<?>> resources = new HashSet<>();
addRestResourceClasses(resources);
resources.add(MultiPartFeature.class);
return resources;
}
/**
* Do not modify addRestResourceClasses() method. It is automatically
* populated with all resources defined in the project. If required, comment
* out calling this method in getClasses().
*/
private void addRestResourceClasses(Set<Class<?>> resources) {
resources.add(mypackage.service.MYSERVICE.class);
}
}
On myweb.xml I have:
<servlet>
<servlet-name>ServletAdaptor</servlet-name>
<servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
<init-param>
<param-name>javax.ws.rs.Application</param-name>
<param-value>mypackage.service.ApplicationConfig</param-value>
</init-param>
<init-param>
<param-name>jersey.config.server.provider.packages</param-name>
<param-value>mypackage.service</param-value>
</init-param>
<init-param>
<param-name>jersey.config.server.provider.classnames</param-name>
<param-value>org.glassfish.jersey.filter.LoggingFilter;org.glassfish.jersey.media.multipart.MultiPartFeature</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>ServletAdaptor</servlet-name>
<url-pattern>/createSomething/*</url-pattern>
</servlet-mapping>
I still get the same message:
Caused by: org.apache.catalina.LifecycleException: org.glassfish.jersey.server.model.ModelValidationException: Validation of the application resource model has failed during application initialization.
[[FATAL] No injection source found for a parameter of type public javax.ws.rs.core.Response
What I´m doing wrong??
It works fine for me. Though I would completely get rid of the Application subclass. It is not needed, and may cause conflict/confusion. Your xml is sufficient configuration, just get rid of the javax.ws.rs.Application <init-param>. I would also look into making the multipart jars only compile-time jars (meaning not built into the war - they might conflict with Glassfish's version). I don't work much with Ant, so I'm not sure how you can do that, but I know it's possible.
Below code worked for me:
Class ->>> add it
Class Property --->> add it
Public Class userREST () {
#POST
#Path("upload")
#Consumes(MediaType.MULTIPART_FORM_DATA)
#Produces(MediaType.APPLICATION_JSON)
public Response uploadImageFile(#FormDataParam("uploadFile") InputStream fileInputStream,
#FormDataParam("uploadFile") FormDataContentDisposition fileFormDataContentDisposition,
#FormDataParam("FIR_REG_NUM") String FIR_REG_NUM, #FormDataParam("LOGIN_ID") String LOGIN_ID) {
final_json_result = WriteFileInFolder.fileAnalysis(fileInputStream, fileFormDataContentDisposition, FIR_REG_NUM,
LOGIN_ID);
return Response.ok(final_json_result).build();
}// uploadImageFile
package ####.jaxrs.jwt;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import javax.ws.rs.ApplicationPath;
import javax.ws.rs.core.Application;
import ####.helper.Common###;
import ####.jaxrs.jwt.filters.JWTRequestFilter;
import ####.jaxrs.jwt.filters.JWTResponseFilter;
import ####.service.FileServicesREST;
#ApplicationPath("fileservice")
public class FileJAXRSConfig extends Application {
#Override
public Set<Class<?>> getClasses() {
Common###.logging("#ApplicationPath#FileServicesREST...");
Set<Class<?>> clazzes = new HashSet<Class<?>>();
clazzes.add(JWTRequestFilter.class);
clazzes.add(FileServicesREST.class);
clazzes.add(JWTResponseFilter.class);
return clazzes;
}
#Override
public Map<String, Object> getProperties() {
Map<String, Object> properties = new HashMap<String, Object>();
properties.put("jersey.config.server.provider.packages", "####.service");
properties.put("jersey.config.server.provider.classnames", "org.glassfish.jersey.media.multipart.MultiPartFeature");
return properties;
}
}
Don't need to add following in web.xml
<init-param>
<param-name>jersey.config.server.provider.packages</param-name>
<param-value>mha.###.service</param-value>
</init-param>
<init-param>
<param-name>jersey.config.server.provider.classnames</param-name>
<param-value>org.glassfish.jersey.media.multipart.MultiPartFeature</param-value>
</init-param>
Okay, this question has probably been asked before, but on all sites I've looked the explanation on "how to do this" tells me I'm doing it completely right.
I know I'm not, as I get a 500 server error on my localhost tomcat and I get the following error in my server logs:
javax.ws.rs.WebApplicationException: com.sun.jersey.api.MessageException: A message body writer for Java class com.myapp.domain.Location, and Java type class com.myapp.domain.Location, and MIME media type application/json was not found
So, what I'm trying to do is to develop a RESTful web service with Jersey (in Java). Everything is going fine, except for the fact that I want to return JSON. I can't find what I'm doing different from these people:
How to send response as JSON in Jersey Rest
http://www.jasonwhaley.com/blog/2011/01/18/multiple-content-types-in-jax-rs/
https://github.com/jasonray/jersey-starterkit/wiki/Serializing-a-POJO-to-xml-or-json-using-JAXB
https://github.com/jasonray/jersey-starterkit/wiki/Serializing-a-POJO-to-json-using-built-in-jersey-support
http://www.vogella.com/tutorials/REST/article.html
My POJO (Location) looks like this:
package com.myapp.domain;
import javax.xml.bind.annotation.XmlRootElement;
#XmlRootElement()
public class Location {
private int id;
private double longtitude;
private double latitude;
public Location() {
new Location(-1, -1, -1);
}
public Location(double longtitude, double latitude) {
new Location(-1, longtitude, latitude);
}
public Location(int id, double longtitude, double latitude) {
this.id = id;
this.longtitude = longtitude;
this.latitude = latitude;
}
public void setID(int id) {
this.id = id;
}
public void setLongtitude(double longtitude) {
this.longtitude = longtitude;
}
public void setLatitude(double latitude) {
this.latitude = latitude;
}
public int getID() {
return this.id;
}
public double getLongtitude() {
return this.longtitude;
}
public double getLatitude() {
return this.latitude;
}
}
My resource looks like this:
package com.myapp.MyAPP;
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.myapp.domain.Location;
#Path("Locations")
public class LocationInfo {
#GET
#Path("/get/{id}")
#Produces(MediaType.APPLICATION_JSON)
public Location getLocation(#PathParam("id") int id) {
Location loc = new Location(3, 4.007391, 51.00237);
return loc;
}
}
And this is my web.xml:
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
id="WebApp_ID"
version="2.5">
<display-name>MyAPP</display-name>
<servlet>
<servlet-name>MyAPP REST Service</servlet-name>
<servlet-class>com.sun.jersey.spi.container.servlet.ServletContainer</servlet-class>
<init-param>
<param-name>com.sun.jersey.config.property.packages</param-name>
<param-value>com.myapp.MyAPP</param-value>
</init-param>
<init-param>
<param-name>com.sun.jersey.api.json.POJOMappingFeature</param-name>
<param-value>true</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>MyAPP REST Service</servlet-name>
<url-pattern>/rest/*</url-pattern>
</servlet-mapping>
</web-app>
I've got these libraries included: asm-3.1.jar, jersey-client-1.17.1.jar, jersey-core-1.17.1.jar, jersey-json-1.17.1.jar, jersey-server-1.17.1.jar, jersey-servlet-1.17.jar, jsr11-api-1.1.1.jar
The one who sees what I'm not seeing gets a beer. Or at least my eternal gratitude, cause I've been looking at this for way too long and I still can't see it.
Okay, so I turned out orid had the right answer: I simply needed to add some extra libraries!
I probably overlooked it or most tutorials probably suppose you add all the libraries you download with jersey straight away...
So this fixed the problem: adding
jackson-core-asl-1.9.2.jar
jackson-jaxrs-1.9.2.jar
jackson-mapper-asl-1.9.2.jar
jackson-xc-1.9.2.jar
Thanks again to orid, you just saved my weekend.
I have some experience using Jersey < 2.0. Now I am trying to build a war application to provide a JSON Webservice API.
I am now struggling for a considerable amount of time trying to configure Moxy and it seams to be way more complicated than what was adding
<init-param>
<param-name>com.sun.jersey.api.json.POJOMappingFeature</param-name>
<param-value>true</param-value>
</init-param>
to your web.xml back in Jersey < 2.0.
Is there some possibility to just say "please add json support"?
Currently I just get a lot of Internal Server Error errors without any log entries on the server and just think "I have to do something totally wrong, this can't be so hard"
Can anyone give me a hint?
Please use the below dependency which will do it automatically for you.
<dependency>
<groupId>com.fasterxml.jackson.jaxrs</groupId>
<artifactId>jackson-jaxrs-json-provider</artifactId>
<version>2.2.3</version>
</dependency>
If you want to define it in your web.xml file then:
JACKSON:
<init-param>
<param-name>jersey.config.server.provider.classnames</param-name>
<param-value>org.glassfish.jersey.jackson.JacksonFeature</param-value>
</init-param>
MOXY
<init-param>
<param-name>jersey.config.server.provider.classnames</param-name>
<param-value>org.glassfish.jersey.moxy.json.MoxyFeature</param-value>
</init-param>
And if using maven add the following dependency to your pom file
JACKSON
<dependency>
<groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-media-json-jackson</artifactId>
<version>your jersey version</version>
</dependency>
MOXY
<dependency>
<groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-media-moxy</artifactId>
<version>your jersey version</version>
</dependency>
You can configure EclipseLink MOXy as the JSON-binding provider by configuring the MOXyJsonProvider class through a JAX-RS Application class.
Example #1
package org.example;
import java.util.*;
import javax.ws.rs.core.Application;
import org.eclipse.persistence.jaxb.rs.MOXyJsonProvider;
public class CustomerApplication extends Application {
#Override
public Set<Class<?>> getClasses() {
HashSet<Class<?>> set = new HashSet<Class<?>>(2);
set.add(MOXyJsonProvider.class);
set.add(CustomerService.class);
return set;
}
}
Example #2
package org.example;
import java.util.*;
import javax.ws.rs.core.Application;
import org.eclipse.persistence.jaxb.rs.MOXyJsonProvider;
public class CustomerApplication extends Application {
#Override
public Set<Class<?>> getClasses() {
HashSet<Class<?>> set = new HashSet<Class<?>>(1);
set.add(ExampleService.class);
return set;
}
#Override
public Set<Object> getSingletons() {
MOXyJsonProvider moxyJsonProvider = new MOXyJsonProvider();
moxyJsonProvider.setAttributePrefix("#");
moxyJsonProvider.setFormattedOutput(true);
moxyJsonProvider.setIncludeRoot(true);
moxyJsonProvider.setMarshalEmptyCollections(false);
moxyJsonProvider.setValueWrapper("$");
Map<String, String> namespacePrefixMapper = new HashMap<String, String>(1);
namespacePrefixMapper.put("http://www.example.org/customer", "cust");
moxyJsonProvider.setNamespacePrefixMapper(namespacePrefixMapper);
moxyJsonProvider.setNamespaceSeparator(':');
HashSet<Object> set = new HashSet<Object>(1);
set.add(moxyJsonProvider);
return set;
}
}
For More Information
http://blog.bdoughan.com/2012/05/moxy-as-your-jax-rs-json-provider.html
http://blog.bdoughan.com/2013/06/moxy-is-new-default-json-binding.html
ACtually, it just worked for me, with the PojoMappingFeature param omitted.
Going to:
http://localhost:8080/webapi/myresource/complexObject/foo
yields this json:
{"name":"foo","value1":1374185178829,"value2":42}
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">
<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.example</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>
entry point:
package com.example;
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;
/**
* Root resource (exposed at "myresource" path)
*/
#Path("myresource")
public class MyResource {
/**
* Method handling HTTP GET requests. The returned object will be sent
* to the client as "text/plain" media type.
*
* #return String that will be returned as a text/plain response.
*/
#GET
#Produces(MediaType.TEXT_PLAIN)
public String getIt() {
return "Got it!";
}
#Path( "complexObject/{name}" )
#GET
#Produces( { MediaType.APPLICATION_JSON } )
public ComplexObject complexObject( #PathParam( "name" ) String name ) {
return new ComplexObject(name, System.currentTimeMillis(), 42L);
}
}
bean to jsonize:
package com.example;
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;
/**
* Root resource (exposed at "myresource" path)
*/
#Path("myresource")
public class MyResource {
/**
* Method handling HTTP GET requests. The returned object will be sent
* to the client as "text/plain" media type.
*
* #return String that will be returned as a text/plain response.
*/
#GET
#Produces(MediaType.TEXT_PLAIN)
public String getIt() {
return "Got it!";
}
#Path( "complexObject/{name}" )
#GET
#Produces( { MediaType.APPLICATION_JSON } )
public ComplexObject complexObject( #PathParam( "name" ) String name ) {
return new ComplexObject(name, System.currentTimeMillis(), 42L);
}
}
Found this as well working, and was the easiest in resolving the problem (AFAIT)
Include the below dependency in your pom.xml / include the respective JAR file in lib path
<dependency>
<groupId>com.owlike</groupId>
<artifactId>genson</artifactId>
<version>0.99</version>
</dependency
Link here
Just use #XmlElement in place of #XmlAttribute (only attribute receives # prefix, possibly restart your appserver for changed effect!)