mehandih / grails-jaxrs

Automatically exported from code.google.com/p/grails-jaxrs
0 stars 0 forks source link

Cannot Marshal Non-Domain Class as JSON: A message body writer for XXXX, and Java type class XXX, and MIME media type application/json was not found #59

Closed GoogleCodeExporter closed 8 years ago

GoogleCodeExporter commented 8 years ago
Trying to marshal a non-domain groovy class to/from JSON (application/json) 
format from a jaxrs plug-in generated resource class does not seem to work. I 
get an exception: 

"A message body writer for XXXX, and Java type class XXX, and MIME media type 
application/json was not found"

With XML (application/xml) it works.

I did this:

1. grails create-resource XXX
2. Added a method: 

    @GET
    @Path('{id}')
    @Produces(['application/xml','application/json'])
    Response read(@PathParam("id") int id) {
        // domain class
        User user = userResourceService.read(id)

        // non-domain class - contains extra "link" parameter.
        // It is annotated with JAXB annotations
        UserDTO dto = getUserDTO(user)
        Response.ok(dto).build()
     }

3. When I try to do a GET with application/json, I get the error above. With 
xml it works.

I found this post:
http://groups.google.com/group/grails-jaxrs-discuss/msg/47900f0cd5268fd7

It says to include the jersey-json module. I tried this, but it still does not 
work. (To BuildConfig.groovy, I added a dependency to 
"runtime('com.sun.jersey:jersey-json:1.11') {    transitive = false }"

Is there something that's missing?

Here is the class to be marshaled:

package securityservicejr

import javax.xml.bind.annotation.XmlElement
import javax.xml.bind.annotation.XmlRootElement
import javax.xml.bind.annotation.XmlAttribute
import javax.xml.bind.annotation.XmlAccessorType
import javax.xml.bind.annotation.XmlAccessType

@XmlAccessorType( XmlAccessType.NONE )
@XmlRootElement(name = "user")
class UserDTO {

    @XmlAttribute
    int id

    @XmlElement(name = "link")
    String updateURI

    @XmlElement
    String userId

    @XmlElement
    String firstName

    @XmlElement
    String lastName

    @XmlElement
    String email
}

Original issue reported on code.google.com by kroy.hou...@gmail.com on 21 Feb 2012 at 10:44

GoogleCodeExporter commented 8 years ago
Thanks for reporting. I'm a bit busy at the moment and will take a closer look 
later this week. Cheers, Martin

Original comment by krass...@googlemail.com on 22 Feb 2012 at 3:21

GoogleCodeExporter commented 8 years ago
You'll need to include transitive deps as well because jersey-json depends on 
the Jackson JSON lib. I just tried to make the plugin dependent on jersey-json 
by default but getting runtime errors. Will investigate now and let you know ...

Original comment by krass...@googlemail.com on 24 Feb 2012 at 8:06

GoogleCodeExporter commented 8 years ago
I was able to run your example even with a non-transitive jersey-json 
dependency. It is now included by default in the latest development version 
(https://github.com/krasserm/grails-jaxrs/commit/04a2ea05e4b144bc8981411feb2eeae
8953a6689). Please build the plugin from the sources and try again.

Original comment by krass...@googlemail.com on 24 Feb 2012 at 9:21

GoogleCodeExporter commented 8 years ago
I downloaded the src, rebuilt the plugin, and then tried again, and I did not 
have much success. Iowuld like to use this plugin, as it does take care of the 
marshaling if I can get this to work (we require both xml and json). 

Any help would be appreciated.

My stacktrace is this:

| Error 2012-02-27 22:54:22,051 ["http-bio-8080"-exec-1] ERROR container.Contain
erRequest  - A message body reader for Java class TestJaxrs2.UserDTO, and Java t
ype class TestJaxrs2.UserDTO, and MIME media type application/json; charset=UTF-
8 was not found.
The registered message body readers compatible with the MIME media type are:
application/json; charset=UTF-8 ->
  org.grails.jaxrs.provider.JSONReader
  org.grails.jaxrs.provider.DomainObjectReader
*/* ->
  com.sun.jersey.core.impl.provider.entity.FormProvider
  com.sun.jersey.core.impl.provider.entity.MimeMultipartProvider
  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.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

I tried adding these dependencies in BuildConfig.groovy, and it did not help:

    dependencies {
        // specify dependencies here under either 'build', 'compile', 'runtime', 'test' or 'provided' scopes eg.

        // runtime 'mysql:mysql-connector-java:5.1.16'
        compile('javax.mail:mail:1.4.4',
                //'javax.xml.bind:jaxb-api:2.2.6',
                'javax.xml.stream:stax-api:1.0-2',
                'org.json:json:20090211',
                'org.codehaus.jackson:jackson-core-asl:1.9.4',
                'org.restlet.jee:org.restlet.ext.jackson:2.0.10') {
            //transitive = false
        }

        runtime('javax.mail:mail:1.4.4',
                //'javax.xml.bind:jaxb-api:2.2.6',
                'javax.xml.stream:stax-api:1.0-2',
                'org.json:json:20090211',
                'org.codehaus.jackson:jackson-core-asl:1.9.4',
                'org.restlet.jee:org.restlet.ext.jackson:2.0.10') {
        //transitive = false
        }

Original comment by kroy.hou...@gmail.com on 28 Feb 2012 at 5:02

GoogleCodeExporter commented 8 years ago
Also, the "UserResource" class I am using is the one below. Note that in my 
inital post here, there was no object in the api being marshaled. Here below, I 
have a non-domain groovy class:

@Path('/api/user')
@Consumes(['application/xml','application/json'])
@Produces(['application/xml','application/json'])
class UserResource {

    @POST
    Response createJson(UserDTO dto) {
        Response.ok(dto).build()
    }

}

Original comment by kroy.hou...@gmail.com on 28 Feb 2012 at 5:30

GoogleCodeExporter commented 8 years ago
I tried with Jersey as JAX-RS impl. Jersey comes with the relevant JSON message 
body reader/writer. Any special reason why you're using Restlet?

Original comment by krass...@googlemail.com on 28 Feb 2012 at 12:09

GoogleCodeExporter commented 8 years ago
I tried restlet to see if it would work. I also had a problem with restlet. It 
also got a 415 unsupported media type. I am having the problem with both Jersey 
and Restlet.

Original comment by kroy.hou...@gmail.com on 28 Feb 2012 at 1:23

GoogleCodeExporter commented 8 years ago
Create a small example application (using Jersey), small enough to only 
reproduce the problem, and 

- either share as it new project on github (preferred)
- or attach it to this ticket

I'll try to get it running then. Please also add instruction to interact with 
the example app, such as which content and headers to send with curl, or 
similar ...

Original comment by krass...@googlemail.com on 28 Feb 2012 at 2:33

GoogleCodeExporter commented 8 years ago
I appreciate your help. If I can get it going, it can save a lot of coding of 
our REST services we will be building. Attached is a small example. To test, I 
am using firefox Rest Client. I attached a zip file with a small project that 
has the problem. There is also a screenshot from firefox 
(Issue-59-TestJaxrs3-Unsupported-Media-Type.jpg)

I set set the following on my request:

METHOD: POST
Headers:
accept = application/json
content-type = application/json

body:
{
  "user": {
    "userId": "Ditto",
    "firstName":"Ditto",
    "lastName":"Jones",
   "email":"djones@company.com"
  }
}

Original comment by kroy.hou...@gmail.com on 28 Feb 2012 at 4:16

Attachments:

GoogleCodeExporter commented 8 years ago
ok thanks, will try to get it running tomorrow

Original comment by krass...@googlemail.com on 28 Feb 2012 at 4:34

GoogleCodeExporter commented 8 years ago
Your example looks ok. Here's what I tested with 'curl'

curl -v -H "Accept: application/json" 
http://localhost:8080/TestJaxrs3/api/user/1

yields

* About to connect() to localhost port 8080 (#0)
*   Trying 127.0.0.1... connected
* Connected to localhost (127.0.0.1) port 8080 (#0)
> GET /TestJaxrs3/api/user/1 HTTP/1.1
> User-Agent: curl/7.19.7 (universal-apple-darwin10.0) libcurl/7.19.7 
OpenSSL/0.9.8r zlib/1.2.3
> Host: localhost:8080
> Accept: application/json
> 
< HTTP/1.1 200 OK
< Server: Apache-Coyote/1.1
< Content-Type: application/json
< Transfer-Encoding: chunked
< Date: Wed, 29 Feb 2012 08:19:59 GMT
< 
* Connection #0 to host localhost left intact
* Closing connection #0
{"@id":"1","userId":"c","firstName":"a","lastName":"b","email":"e"}

and 

curl -v -H "Accept: application/json" -H "Content-Type: application/json" -d 
'{"@id":"1","userId":"c","firstName":"a","lastName":"b","email":"x"}' 
http://localhost:8080/TestJaxrs3/api/user

yields

* About to connect() to localhost port 8080 (#0)
*   Trying 127.0.0.1... connected
* Connected to localhost (127.0.0.1) port 8080 (#0)
> POST /TestJaxrs3/api/user HTTP/1.1
> User-Agent: curl/7.19.7 (universal-apple-darwin10.0) libcurl/7.19.7 
OpenSSL/0.9.8r zlib/1.2.3
> Host: localhost:8080
> Accept: application/json
> Content-Type: application/json
> Content-Length: 67
> 
< HTTP/1.1 200 OK
< Server: Apache-Coyote/1.1
< Content-Type: application/json
< Transfer-Encoding: chunked
< Date: Wed, 29 Feb 2012 08:23:07 GMT
< 
* Connection #0 to host localhost left intact
* Closing connection #0
{"@id":"1","userId":"c","firstName":"a","lastName":"b","email":"x"}

Can you reproduce? Btw, 'text/json', as used in your screenshot, is not a valid 
MIME type, you should use application/json.

Does that help?

Original comment by krass...@googlemail.com on 29 Feb 2012 at 8:28

GoogleCodeExporter commented 8 years ago

Original comment by krass...@googlemail.com on 29 Feb 2012 at 8:30

GoogleCodeExporter commented 8 years ago
OK. I got it to work. What I did: 

1) deleted my .grails directory
2) recreated the grails app
3) Installed my locally built 0.7 jaxrs plugin (with your fix).
4) In changed the json I was sending in. I was specifying a high level "user" 
element. In your example, it is not there.

(4) Above was not the problem that was causing the media type issue. I think 
what made it all work was deleting my .grails, and starting fresh. I did try 
application/json originally, but I was just trying different things.

QUESTION: Will you be creating a 0.7 jaxrs plugin anytime soon?

Sorry for all the trouble.

Original comment by kroy.hou...@gmail.com on 29 Feb 2012 at 10:18

GoogleCodeExporter commented 8 years ago
a 0.7 release will take a while but I could cut a 0.6.1 release with that fix, 
although I cannot say when I'll have time doing that - pretty busy with other 
stuff at the moment. Anyway, you can always clone the github repo and create a 
tag from the latest version of master, then you have a fixed version to refer 
to in the meantime. Hope that helps.

Cheers,
Martin

Original comment by krass...@googlemail.com on 2 Mar 2012 at 6:09

GoogleCodeExporter commented 8 years ago
To make this work in v0.6 I had to manually copy jersey-json jar to the 
plugin's directory under .grails/projects.

Original comment by ivgorg...@gmail.com on 31 May 2012 at 12:12

GoogleCodeExporter commented 8 years ago
Is the plugin with changes got released?.

Original comment by vkon...@stockpile.com on 23 Dec 2012 at 2:43

GoogleCodeExporter commented 8 years ago
Not yet, please use the development snapshot from master. Thanks.

Original comment by krass...@googlemail.com on 23 Dec 2012 at 10:50

GoogleCodeExporter commented 8 years ago
I cant find the development snapshot. Can you share the link please. Or any 
idea when 0.7 will be released?.

Original comment by kone...@gmail.com on 24 Dec 2012 at 3:29

GoogleCodeExporter commented 8 years ago
You need to build it yourself as described at 
http://code.google.com/p/grails-jaxrs/wiki/InstallationInstructions#Sources.

Original comment by krass...@googlemail.com on 24 Dec 2012 at 3:09