Error returning custom object via GET method - rest

I am trying to run a simple example in Jersey which has a GET method and returns a Custom object.
on calling GET I am getting following error
MessageBodyWriter not found for media type=text/plain
I have looked into few answers on stackoverflow where they are suggesting it to put a default constructor and jackson dependency in pom.xml. I have already done that but no luck. Can some one please suggest what I am doing wrong.
Resource Class
#Path("customdatatyperesource")
public class CustomDataTypeResource {
#GET
public CustomResource1 get(#Context UriInfo ui) {
return new CustomResource1();
}
}
Custom Class
#XmlRootElement
public class CustomResource1 {
#XmlElement
String res;
public CustomResource1() { }
#Override
public String toString(){
return "Custom : "+res;
}
}
pom.xml
Thanks

So I figured out that error is not in the code but in the request sent.
When I send the request with header accept: text/plain
I am getting the error MessageBodyWriter not found for media type=text/plain
The resolution is accept header needs to match with what resource can produce.
In this case our resource is capable of producing XML or JSON
A better and more comprehensive way to write this code would be to put produce annotation on the methods.
#Produces(MediaType.TEXT_XML)
and put correct accept header such as
accept: application/json

Related

Different Jersey 2 response depending on media type (JSON/XML)

In a RESTful Glassfish 4 application (JERSEY 2.22.2, MOXY as JSON Provider), we have a resource method that is able to produce both JSON and XML outputs.
The method response passes through a MessageBodyWriter, but it's used to build an Object Graph only in certain cases. In these cases, independently from the requested media type from the client, the graph is applied correctly.
On the other hand, when the isWriteable() method of our MessageBodyWirter returns false, therefore passing on to the next writer in the writers list of the MessageBodyFactory, the behavior is different between a JSON media type request and an XML media type request (i.e. Accept: application/json and Accept: application/xml respectively in the request headers).
In the first case, the FilteringMoxyJsonProvider is selected as response writer, because the EntityFilteringFeature is registered. The response is written based on the entity filtering annotations.
Though when the client asks for an XML response, another MessageBodyWriter (org.glassfish.jersey.jaxb.internal.XmlRootElementJaxbProvider) is selected.
This is due to the ordering of the WriterModels in the MessageBodyFactory in which the FilteringMoxyJsonProvider is positioned after XmlRootElementJaxbProvider.
In this situation the XML response is written without having any filters applied to it.
We tried to look for a way to change the writers order, also tried to access to the EntityFieldProcessor class, without luck.
Is it possible to have both scenarios (i.e. JSON and XML response requests) work in the same way? Is it possible to exclude some writers from being registered or to change their order in the MessageBodyFactory?
Any help will be appreciated.
//Configuration
public class ApplicationConfigVersione1 extends ResourceConfig {
....
register(EntityFilteringFeature.class);
register(MyCustomWriter.class);
------------------------
#Produces({"application/json", "application/xml"})
public class MyCustomWriter implements MessageBodyWriter<MyCustomObject> {
....
#Override
public boolean isWriteable(Class<?> type, Type genericType,
Annotation[] annotations, MediaType mediaType) {
if (mustUseCustomWriter()) {
return true;
} else {
return false;
//In this case, with request header accept=application/xml, the xml response is not filtered.
}
}
#Override
public void writeTo(MyCustomObject customObject, Class<?> type, Type genericType, Annotation[] annotations,
MediaType mediaType,
MultivaluedMap<String, Object> httpHeaders, OutputStream entityStream)
throws IOException, WebApplicationException {
objectGraph = buildObjectGraph();
marshaller.setProperty(MarshallerProperties.OBJECT_GRAPH, objectGraph);
marshaller.setProperty(MarshallerProperties.MEDIA_TYPE, mediaType.toString());
//**** objectGraph applies to XML and JSON media types
marshaller.marshall(object, entityStream);
I have also tried to use Jersey's Entity Filtering mechanism with resources producing both application/json and application/xml responses and see different result information according to the repsonse type.
I suspect this closed/wont-fix github issue for the moxy component is the cause of the behaviour we are seeing with filtering: https://github.com/jersey/jersey/issues/3036

#BeanParam gives exception A message body reader for Java class was not found

I am trying to make a jersey based web service. In this if i take input params using #FormParam it works fine:
#POST
#Consumes({MediaType.TEXT_PLAIN, MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON, MediaType.TEXT_HTML, "application/x-www-form-urlencoded"})
#Path("/registeruser")
public Response registerUser(#FormParam ("email") String email,#FormParam ("name") String name ){
System.out.println("Inside register device");
System.out.println("registered" + email);
return null;
}
but when I try using #BeanParam it does not works and gives me an exception
#POST
#Consumes({MediaType.TEXT_PLAIN, MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON, MediaType.TEXT_HTML, "application/x-www-form-urlencoded"})
#Path("/registeruser")
public Response registerUser(#BeanParam UserForm userForm ){
System.out.println("Inside register device");
service.registerUser(userForm);
System.out.println("registered" + userForm.getEmail());
return null;
}
A message body reader for Java class com.stc.dms.forms.UserForm, and Java type class com.stc.dms.forms.UserForm, and MIME media type application/octet-stream was not found.
You don't need to use #BeanParam to pass an object as input. Just pass it like this :
#POST
#Path("register")
#Consumes(MediaType.APPLICATION_JSON)
public Response registerUser(UserForm dto) {
// ...
}
Just make sure to include the libraries for producing/consuming json. If the client is in javascript you don't need anything else (just use JSON.stringify() on your form object), for the server add some json libraries such as Jackson
EDIT :
If you want to stick with #BeanParam, take a look at this tutorial here. Basically it seems that you don't need to specify the mediatype, as Jersey will handle that for you.

How can I specify the default MimeType returned by a REST resource with Jersey

I am creating a REST interface and have a resource 'data'. Now I want that an user can specify whether he wants the data as XML or as JSON. Therefore I have created two methods for the same path, one produces application/xml, the other produces application/json. Everything works fine, but how can I specify what should be returned, if an user doesn't set the 'Accept' header field?
My tests have shown that it is not always the same. Yesterday the default was application/xml, today my tests have failed, because as default application/json was returned.
How can I specify a default?
Code Snippet:
#GET
#Path("/rest/data")
#Produces(MediaType.APPLICATION.XML)
public Object getDataAsXML() {
// return data in XML format
}
#GET
#Path("/rest/data")
#Produces(MediaType.APPLICATION_JSON)
public Object getDataAsJSON() {
// return data in JSON format
}
Cheers,
metalhamster
#Path("/myResource")
#Produces("text/plain")// doGetAsPlainText method defaults to the MIME type of the #Produces annotation at the class level.
public class SomeResource {
#GET
public String doGetAsPlainText() {
...
}
#GET
#Produces("text/html")
public String doGetAsHtml() {
...
}
}
The doGetAsPlainText method defaults to the MIME type of the #Produces annotation at the class level. The doGetAsHtml method's #Produces annotation overrides the class-level #Produces setting, and specifies that the method can produce HTML rather than plain text.
#GET
#Produces({"application/xml", "application/json"})
public String doGetAsXmlOrJson() {
...
}
The doGetAsXmlOrJson method will get invoked if either of the media types "application/xml" and "application/json" are acceptable. If both are equally acceptable then the former will be chosen because it occurs first.
#Produce

How to handle requests with unsupported content type correctly?

I have a REST interface build with Jersey. Actually I only support as content type only application/json for all incoming requests. That is why I defined my message body reader and writer as
#Provider
#Consumes(MediaType.APPLICATION_JSON)
#Produces(MediaType.APPLICATION_JSON)
public class MarshallerProvider
implements MessageBodyReader<Object>, MessageBodyWriter<Object>
{
}
Now I wrote a test where I try to get a document via GET and expected content type application/xml. Jersey answers this request with an MessageBodyProviderNotFoundException.
So what would be the best way to handle such unsupported requests correctly? Should I write an exception mapper? Since it is an internal exception I don't like this approach?
The solution should allow me to return an HTTP 415 (Unsupported Media Type).
Yes, avoid exception handlers, handle this case with methods:
#Path("example")
public class Example {
#GET
public Response getBadStuff() {
return Response.status(Response.Status.UNSUPPORTED_MEDIA_TYPE).build();
}
#GET
#Produces(MediaType.APPLICATION_JSON)
public Object getGoodStuff() {
return myObject;
}
}

POST method to grails resource - Unsupported Media Type

I would like to send some data with POST to my grails application.
I have got a really easy domain:
class Step {
String name;
Long taskId = -1;
static constraints = {
}
}
I implemented service for it:
#Path('/api/step')
class StepResource {
#POST
#Consumes(['application/json'])
String create(Step dto) {
// dto.save()
}
}
I added plugin to Google Chrome to test it - POSTMAN and try to POST.
The result is:
The grails console prints:
| Error 2013-06-08 23:30:25,574 [http-bio-8080-exec-3] ERROR container.ContainerRequest - A message body reader for Java class java.lang.Object, and Java type class java.lang.Object, and MIME media type application/json was not found.
The registered message body readers compatible with the MIME media type are:
application/json ->
com.sun.jersey.json.impl.provider.entity.JSONJAXBElementProvider$App
com.sun.jersey.json.impl.provider.entity.JSONRootElementProvider$App
com.sun.jersey.json.impl.provider.entity.JSONListElementProvider$App
*/* ->
com.sun.jersey.core.impl.provider.entity.FormProvider
com.sun.jersey.core.impl.provider.entity.StringProvider
com.sun.jersey.core.impl.provider.entity.ByteArrayProvider
com.sun.jersey.core.impl.provider.entity.FileProvider
com.sun.jersey.core.impl.provider.entity.InputStreamProvider
com.sun.jersey.core.impl.provider.entity.DataSourceProvider
com.sun.jersey.core.impl.provider.entity.XMLJAXBElementProvider$General
com.sun.jersey.core.impl.provider.entity.ReaderProvider
com.sun.jersey.core.impl.provider.entity.DocumentProvider
com.sun.jersey.core.impl.provider.entity.SourceProvider$StreamSourceReader
com.sun.jersey.core.impl.provider.entity.SourceProvider$SAXSourceReader
com.sun.jersey.core.impl.provider.entity.SourceProvider$DOMSourceReader
com.sun.jersey.json.impl.provider.entity.JSONJAXBElementProvider$General
com.sun.jersey.core.impl.provider.entity.XMLRootElementProvider$General
com.sun.jersey.core.impl.provider.entity.XMLListElementProvider$General
com.sun.jersey.core.impl.provider.entity.XMLRootObjectProvider$General
com.sun.jersey.core.impl.provider.entity.EntityHolderReader
com.sun.jersey.json.impl.provider.entity.JSONRootElementProvider$General
com.sun.jersey.json.impl.provider.entity.JSONListElementProvider$General
Could you give me any solution ?
I am not sure you should print it..
just declare the string
Also change the method type to String
Also go over the documentation. It's the easiest approach
https://github.com/krasserm/grails-jaxrs/wiki/Getting-Started