I have some JAX-RS web services with method signatures like below. Is it possible to print out the raw JSON requests coming from the clients and raw JSON response returned to the clients?
#POST
#Consumes(MediaType.APPLICATION_JSON)
#Produces(MediaType.APPLICATION_JSON)
public Response XXX(#Context HttpServletRequest request, Parameters requestParameters) {
...
}
Thanks in advance.
this can be done via request filter for you. This is my implementation:
#Path("test")
#Produces(MediaType.APPLICATION_JSON)
#Consumes(MediaType.APPLICATION_JSON)
public class HelloResource {
private static final Logger log = Logger.getLogger(HelloResource.class);
#POST
#Path("/test")
public Response test(String body) {
Map<String, String> tmp = new HashMap<>();
tmp.put("test", "value");
return Response.ok(tmp).build();
}
}
The resource for testing. Just takes the body as a string.
Now you can register a ContainerResponseFilter and a ContainerRequestFilter.
These filters will be called before and after the request. Before will print the incoming body, after will print the response body.
It is important to not do both in the response filter because the request entity Stream is closed at the time the response filter is executed.
That is when you want to print your bodies, e.g. like this:
public class PrintFilter implements ContainerResponseFilter, ContainerRequestFilter {
#Override
public void filter(ContainerRequestContext requestContext, ContainerResponseContext responseContext)
throws IOException {
System.out.println("Response body: " + responseContext.getEntity());
}
#Override
public void filter(ContainerRequestContext requestContext) throws IOException {
String string = IOUtils.toString(requestContext.getEntityStream());
System.out.println("request body: " + string);
}
}
I am using apache-commons to read the request Stream into a String.
For my json file, looking like that:
artur#pandaadb:~/tmp/test$ cat 1.json
{
"eventType": 1,
"params": {
"field1" : 10
}
}
I can make a curl, looking like this:
artur#pandaadb:~/tmp/test$ curl -XPOST "localhost:9085/api/test/test" -H "Content-Type: application/json" --data #1.json
{"test":"value"}
Which will print to my console:
request body: { "eventType": 1, "params": { "field1" : 10 }}
Response body: {test=value}
That is obviously only one of many solutions. This would work for all json content types (and frankly most other content types as well I would expect).
Hope that helps,
Artur
Related
Background : I'm calling backend WebServices from Play controller and sending the Response (in JSON format) to AngularJS module wrapped in play.mvc.Result. This integration works seamlessly.
Problem Statement : Now I want to parse the Response and use it for some business logic; but play.mvc.Result class has only one method which is toScala(). How do I get the body of play.mvc.Result.
Can I use play.libs.F.Promise to get my job done?
Below is the Generalized code which takes JSON request body and Service URL as parameter and returns the play.mvc.Result.
WSRequestHolder requestHolder = WS.url("https://application.url/ws/endpoint")
.setHeader("Content-Type", "application/json");
final Promise<String> promise = requestHolder.post(jsonRequest)
.map(new Function<WS.Response, String>() {
#Override
public String apply(final Response a) throws Throwable {
//Do i need to Parse from here???
return a.getBody();
}
});
return Results.async(promise.map(new Function<String, Result>() {
#Override
public Result apply(final String a) throws Throwable {
if(STR_UNAUTHORIZED.equals(a)){
return Results.redirect(controllers.routes.Authentication.login("",""));
}
return Results.ok(a);
}
}));
So is there a way to extract the Response body from play.mvc.Result or is there any alternate way to do this?
Below code would Parse the response from WebService call in synchronized way:
WSRequestHolder requestHolder = WS.url("https://application.url/ws/endpoint")
.setHeader("Content-Type", "application/json");
final Promise<WS.Response> promise = requestHolder.get();
Response myResponse=promise.get(50000);
// This code returns the Parsed response in form of String
return myResponse.getBody();
I've got Angular app and Java server.
I need to send POST request with JSON object consisting of string array and string field.
I'm using Angularjs $resource and Java javax.ws.rs.
My latest try as follows:
Client:
var messages = $resource('resources/messages/getmessages', {}, {
update: { method: 'POST', url: 'resources/messages/updatemessages' }
});
//...
var _args = { 'msgIdList': ['1', '2', '3'],
'action': 'makeSmth' };
return messages.update(_args).$promise.then(
function (data) {
//...
},
function (error) {
//...
}
)
Server:
#POST
#Path("updatemessages")
#Consumes(MediaType.APPLICATION_FORM_URLENCODED)
#Produces(MediaType.APPLICATION_JSON +"; charset=UTF-8")
public Response updateMessages( #FormParam("msgIdList") List<String> msgIdList,
#DefaultValue("") #FormParam("action") String action,
#CookieParam("rgsid") String c_sid,
#Context HttpServletRequest httpservletreq) {
//...
}
The problem is that I've got 415 Unsupported Media Type error, and don't know what to do next. I've tried lots of things, but may be I was wrong from the start, and I can't pass parameters this way?
Any help would be appreciated, thanks!
you can try this in your angular, maybe it can help.
var sendPost = $http({
method: "post",
url:"JAVA_SERVER_SERVICE_URL",
data: {
msgIdList: 'your_value',
action: 'your_value'
},
headers: { 'Content-Type': 'application/json' }
});
So, eventually I made a wrapper class, so now it looks this way:
#XmlRootElement
private static class RequestWrapper {
#XmlElement
private ArrayList<String> msgIdList;
#XmlElement
private String action;
public ArrayList<String> getMsgIdList() {
return msgIdList;
}
public void setMsgIdList(ArrayList<String> msgIdList) {
this.msgIdList = msgIdList;
}
public String getAction() {
return action;
}
public void setAction(String action) {
this.action = action;
}
public RequestWrapper() {
}
}
#POST
#Path("updatemessages")
#Consumes(MediaType.APPLICATION_JSON)
#Produces(MediaType.APPLICATION_JSON +"; charset=UTF-8")
public Response updateMessages( RequestWrapper requestData,
#CookieParam("rgsid") String c_sid,
#Context HttpServletRequest httpservletreq) {
//...}
Angular part stays unchanged.
I'm not really sure, if this the right way to go (class description and so on), but it works.
I've been writing simple dropwizard application, and everything worked fine, untill I had to change request type. As I previously got my arguments from Header, now I have to get them from the body of a JSON request. And the saddest part is - there is no complete documentation for dropwizard or any article, that would help me. Here's my code:
#Path("/actors")
#Produces("application/json")
public class ActorResource {
private final ActorDAO dao;
public ActorResource(ActorDAO dao) {
this.dao = dao;
}
#POST
#UnitOfWork
public Saying postActor(#HeaderParam("actorName") String name,#HeaderParam("actorBirthDate") String birthDate) {
Actor actor = dao.create(new Actor(name,birthDate));
return new Saying("Added : " + actor.toString());
}
Does anyone have a solution?
as requested, here's a snippet demonstrating what you want to do:
#Path("/testPost")
#Produces(MediaType.APPLICATION_JSON)
public class TestResource {
#POST
public Response logEvent(TestClass c) {
System.out.println(c.p1);
return Response.noContent().build();
}
public static class TestClass {
#JsonProperty("p1")
public String p1;
}
}
The TestClass is my body. Jersey knows right away, that it needs to parse the body into that object.
I can then curl my API doing this:
curl -v -XPOST "localhost:8085/api/testPost" -H "Content-Type: application/json" -d '{"p1":"world"}'
Jersey knows by the method parameter what to do, and by the Jackson Annotation how to treat the JSON.
Hope that helps,
Artur
Edit: For the more manual approach, you can:
In your post method, inject
#Context HttpServletRequest request
And from the injected request, write the body into a String for handling:
StringWriter writer = new StringWriter();
try {
IOUtils.copy(request.getInputStream(), writer);
} catch (IOException e) {
throw new IllegalStateException("Failed to read input stream");
}
Now use any library to map that string to whatever Object you want.
I'm trying to get the body of a POST request by using HttpServletRequest or UriInfo. Given a class like this one (reduced for this question):
#Path("/nodes")
#Produces({ MediaType.APPLICATION_JSON })
#Consumes({ MediaType.APPLICATION_JSON })
public class Nodes {
public NodeResource() {
//initial stuff goes here
}
/**
* gives an empty response. For testing only!
*/
#POST
#Consumes("application/json")
#Path("{id}/test-db-requests")
public Response giveNodes(#PathParam("id") final String id, #Context HttpServletRequest request, #Context UriInfo uriInfo){
//String readReq = request.getQueryString(); //would work for GET
MultivaluedMap<String,String> readParams = uriInfo.getQueryParameters();
LOG.debug("what is readParams?", readParams); //goes, but shows nothing
if (readParams != null) {
LOG.debug("null or not?"); //goes, too
for (Map.Entry<String,List<String>> entry: readParams.entrySet()) {
List<String> values = entry.getValue();
LOG.debug("params POST key: {}", entry.getKey()); // goes not
for (String val: values) {
LOG.debug("params POST values: {}", val);
}
LOG.debug("params POST next entry:::");
}
}
List<?> results = null; //currentDBRequest(id);
List<?> content = new ArrayList<>();
if (results != null) {
content = results;
}
return Response.ok(content).build();
}
}
Instead of using
MultivaluedMap<String,String> readParams = uriInfo.getQueryParameters();
//not possible at all - for GET only!? See first comment.
I also tried to use
Map<String,String[]> readParams = request.getParameterMap();
//what is about this one?
with different following code of course. But that did not work, either.
So when I fire a simple request like /nodes/546c9abc975a54c398167306/test-db-requests with the following body
{
"hi":"hello",
"green":"tree"
}
(using an JSON Array does not change anything)
and stuff in the HEADER (some informations):
Content-Type: application/json; charset=UTF-8
Accept: application/json, text/plain, */*
Connection: keep-alive
the result is disappointing, readParams is not null, but does not contain any data. Before I start to play with getReader I wanted to ask: what am I doing wrong? Is there a problem in my POST, in my Java code or in the used HttpServletRequest method(s)? Thanks!
Related questions (where I found some possible solutions), among others:
How can I grab all query parameters in Jersey JaxRS?
How to access parameters in a RESTful POST method
Alright, Jackson would actually do this for me. Just use the argument of the method, which you want to use. (See examples below.)
But you would probably not use a POST in combination with an id parameter. POST is usually used for saving fresh resources, which do not have an id (in the DB, a primary key). Moreover the path /api/{resource_name}/{id}/{some_view} would be useful for GET. Just api/{resource_name}/{id} for a GET (single entry) or a PUT (update an existing entry).
Assume you are in a resource for Pet.class. You want to catch the POSTs for this class in order to do something special with them, based on the view test-db-requests. Then do:
#POST
#Consumes("application/json")
#Path("{id}/test-db-requests")
public Response giveNodes(final String pet, #PathParam("id") final String id){
//do stuff for POST with a strigified JSON here
}
or
#POST
#Path("{id}/test-db-requests")
public Response giveNodes(final Pet pet, #PathParam("id") final String id){
//do stuff for POST with an instance of pet here (useful for non
//polymorphic resources
}
I have a JAX-RS project where the POST is not working. I have #GET URLs which work fine. Everything seems to work fine except this #POST.
#POST
#Path("/json/insert")
#Produces(MediaType.APPLICATION_JSON)
#Consumes("application/x-www-form-urlencoded")
public String postJSONInsert(
#FormParam("instance") String instance,
#FormParam("db") String table) {
String json;
EDPObject edp_obj = new EDPObject();
try {
json = edp_obj.insert("json", instance, table);
} catch(Exception e) {
edp_obj.endSession();
json = handleJSONError(e);
}
return json;
}
Getting 500 not yet connected in firebug when trying this on client:
$.ajax('http://127.0.0.1:8070/sixaxis/webapi/json/insert', {
data: {
db: '17:2',
instance: 'shawn'
},
dataType: 'json',
type: 'POST'
});
Have you tried:
#Consumes(MediaType.APPLICATION_JSON)
since your jQuery is:
dataType:'json'
Update (thanks for the feedback):
Then the method at least should be:
#POST
#Path("/json/insert")
#Produces(MediaType.APPLICATION_JSON)
#Consumes(MediaType.APPLICATION_JSON)
public String postJSONInsert( Map<String,Object> params ){
// Your business logic
}