Reputation: 1495
I have a problem with posting JSON to a Jersey REST service - GET is working perfectly but POST seems tricky. I've been working on this problem for awhile now, with no solution so far. Any help is much appreciated!
It seems it cant find the U RL to send the json?Here is what FireBug console shows:
POST http://localhost:9998/data 400 Bad Request
Post source: name=Tony
**Response Headers**
Connection close
Content-Length 0
Content-Type text/html; charset=iso-8859-1
Date Fri, 20 Apr 2012 10:13:24 GMT
**Request Headers**
Accept application/json, text/javascript, */*; q=0.01
Accept-Encoding gzip, deflate
Accept-Language sv-se,sv;q=0.8,en-us;q=0.5,en;q=0.3
Connection keep-alive
Content-Length 9
Content-Type application/json; charset=UTF-8
Host localhost:9998
Referer http://localhost:9998/static/page.html
User-Agent Mozilla/5.0 (Windows NT 6.1; WOW64; rv:11.0) Gecko/20100101 Firefox/11.0
X-Requested-With XMLHttpRequest
I'm doing the POST as follows:
<button id='btn' value="knapp" name="knapp" />
<script type="text/javascript">
$('#btn').click(function(){
$.ajax({
url: '/data',
type: 'POST',
contentType: 'application/json',
data: {name:"Tony"},
dataType: 'json'
});
})
</script>
Javabean class with @XmlRootElement:
@XmlRootElement
public class StatusBean {
private String name;
public StatusBean() {
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
Resource method:
@Path("/data")
public class PostData {
@POST
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
public StatusBean post(StatusBean sb) {
System.out.println(sb);
return sb;
}
}
The server, set up with Grizzly:
public class Main {
public static final URI BASE_URI = getBaseURI();
public static void main(String[] args) throws IOException {
HttpServer httpServer = startServer();
Map<String,String> initParams = new HashMap<String, String>();
initParams.put("com.sun.jersey.config.property.packages", "server");
SelectorThread selector = GrizzlyWebContainerFactory.create("http://localhost:9998/", initParams );
System.out.println(String.format("Jersey app started with WADL available at "
+ "%sapplication.wadl\nTry out %shelloworld\nHit enter to stop it...",
BASE_URI, BASE_URI));
System.in.read();
httpServer.stop();
}
protected static HttpServer startServer() throws IOException {
System.out.println("Starting grizzly...");
ClassNamesResourceConfig rc = new ClassNamesResourceConfig(PostData.class);
// rc.getFeatures().put(JSONConfiguration.FEATURE_POJO_MAPPING, true);
HttpServer server = GrizzlyServerFactory.createHttpServer(BASE_URI, rc);
server.getServerConfiguration().addHttpHandler(new StaticHttpHandler(new File(".").getAbsolutePath()), "/static");
return server;
}
private static int getPort(int defaultPort) {
String port = System.getProperty("jersey.test.port");
if (null != port) {
try {
return Integer.parseInt(port);
} catch (NumberFormatException e) {
}
}
return defaultPort;
}
private static URI getBaseURI() {
return UriBuilder.fromUri("http://localhost/").port(getPort(9998)).build();
}
}
Upvotes: 5
Views: 13401
Reputation: 1963
You have probably forgotten to register the JSON mapper, i.e. Jackson (or whatever mapper you use). The feature is not enabled automatically, you have to load the class in your ResourceConfig:
org.glassfish.jersey.jackson.JacksonFeature.class
Upvotes: 0
Reputation: 4098
I had the same problem. The issue is that your data is not converted to JSON string automatically. So you just need to call JSON.stringify(...) on your data before posting it:
<button id='btn' value="knapp" name="knapp" />
<script type="text/javascript">
$('#btn').click(function(){
$.ajax({
url: '/data',
type: 'POST',
contentType: 'application/json',
data: JSON.stringify({name:"Tony"}),
dataType: 'json'
});
})
</script>
This should work.
Upvotes: 2
Reputation: 22692
From your server config I see that you haven't configured JAX-RS with Grizzly. On the base of that example you should somehow pass such property
Map<String,String> initParams = new HashMap<String, String>();
initParams.put( "com.sun.jersey.config.property.packages", "package.with.your.StatusBean.class" );
Another configuration option is to use
ResourceConfig rc = new PackagesResourceConfig("your.package.with.resources");
and start grizzly server:
GrizzlyServerFactory.createHttpServer(BASE_URI, rc);
See details: http://jersey.java.net/nonav/documentation/latest/user-guide.html (Chapter "Deploying the root resource"). Try to run first example they have.
Upvotes: 1
Reputation: 4122
Try making your bean serializable.
@XmlRootElement
public class StatusBean implements Serializable {
....
}
Check your POST url. It should be `
http://localhost:9998/{projectname}/{restservletmapping}/data
For example, if my web.xml looks like this and my project name is SampleProject
<servlet-mapping>
<servlet-name>Jersey REST Service</servlet-name>
<url-pattern>/rest/*</url-pattern>
</servlet-mapping>
URL would be : http://localhost:9998/SampleProject/rest/data
You can use tools for testing REST services like SOAP UI or browser addons like POSTMAN, REST CONSOLE, etc.
If above things are fine and REST service is giving response with testing tools. Then it could be problem of Cross Origin Policy in ajax.
Upvotes: 2
Reputation: 54487
Are you sure that the path you're posting to is complete? You should define another Path
annotation on the post
method and use that in the URL you're posting to:
@Path("/data")
public class PostData {
@Path("/postStatus")
@POST
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
public StatusBean post(StatusBean sb) {
System.out.println(sb);
return sb;
}
}
Then use the /data/postStatus
path to post your request to:
<button id='btn' value="knapp" name="knapp" />
<script type="text/javascript">
$('#btn').click(function(){
$.ajax({
url: '/data/postStatus',
type: 'POST',
contentType: 'application/json',
data: {name:"Tony"},
dataType: 'json'
});
})
</script>
Upvotes: 0