Newb to writing Web Services. Am using C#/ASP.Net with WebAPI. End goal is to receive JSON collection, and deserialize the data to database, and inform client application of any failed records, which client will log.
Can the HTTPPost return a collection of the failed rows (as serialized Json) through an IHttpActionResult or HttpResponseMessage, kind of like this:
[HttpPost]
public HttpResponseMessage Post([FromBody]List<Things> t)
{
// deserialize t and process to database
// list of failed records
ICollection<Thing> things= new List<Thing>();
things.Add(...);
things.Add(...);
string jsonFailedRows =
JsonConvert.SerializeObject(things, Formatting.Indented);
// Write the list to the response body
HttpResponseMessage response =
Request.CreateResponse(HttpStatusCode.OK, jsonFailedRows);
return response;
}
I saw this link: StackOverFlow, which says the I can do the following, but is this correct for a Post?
"The latter is done for you if you call the ApiController.Ok() method:
return Ok(jsonFailedRows);
And lastly, is there any way of using CreatedAtRoute to do so?
The solution posted in the linked response indeed answers this question.
I have a grails controller making a REST call using HTTPBuilder to a Spring backend:
def getSettings(String customerID) {
def http = new HTTPBuilder( grailsApplication.config.com.company.product.productWebserviceURL )
def result = [:]
def postBody = [customerID: customerID]
try {
http.post(path: 'product/getSettings', body: postBody, requestContentType: URLENC) { resp, json ->
result = json
}
} catch (IOException ex) {
logger.error("Cannot in attempting to get settings via webservice for customerID: " + customerID + ". Is the server running? \nError: " + ex.getMessage())
result['errors'] = [[message : this.CUSTOMER_FACING_TRANSACTIONHISTORY_DOWN_MESSAGE]]
response.status = 500;
}
render result as JSON
}
Everything is fine, except when getting the JSON response, there is this new property called "new." Here is the Settings object about to be returned as JSON from my Spring backend:
And here it is as the JSON response in the grails controller. Notice the extra fifth property that is not part of the original Settings object.:
Does anyone have an idea how this mysterious property called "new" keeps getting added on?
After running into the spring-data jpa docs here,
I see that spring data will add a property "new" based on if the id column is null or not null. The following is taken directly from the docs:
"Id-Property inspection (default) By default Spring Data JPA inspects the Id-Property of the given Entity. If the Id-Property is null, then the entity will be assumed as new, otherwise as not new."
I'm new to Grails and I'm stuck up with a problem. I want to know if there is a way to send both JSON and view and model through "render" in Grails.
I'm using a jQuery Datatable to display data returned from server which is read from JSON returned by the controller. I also need to display error messages on the same view in case of validation failure in form fields. But I'm able to return either only the JSON or model and view using render. I also tried sending the JSON through model itself but it didn't work.
This is my code:-
def hierarchyBreakInstance = new HierarchyBreak(params);
String json = "{\"sEcho\":\"1\",\"iTotalRecords\":0,\"iTotalDisplayRecords\":0,\"aaData\":[]}";
hierarchyBreakInstance.errors.reject(message(code: 'hierarchyBreak.error.division.blank'));
render(view: "hierarchyBreak", model: [hierarchyBreakInstance: hierarchyBreakInstance]);
//render json;
The gsp code:-
<g:hasErrors bean="${hierarchyBreakInstance}">
<div class="errorMessage" role="alert">
<g:eachError bean="${hierarchyBreakInstance}" var="error">
<g:if test="${error in org.springframework.validation.FieldError}" > data-field-id="${error.field}"</g:if>
<g:message error="${error}"/>
</g:eachError>
</div>
</g:hasErrors>
Could you please let me know if there is a way to do this. Thanks!
You can use like this.
def hierarchyBreakInstance = new HierarchyBreak(params);
String json = "{\"sEcho\":\"1\",\"iTotalRecords\":0,\"iTotalDisplayRecords\":0,\"aaData\":[]}";
hierarchyBreakInstance.errors.reject(message(code: 'hierarchyBreak.error.division.blank'));
render(view: "hierarchyBreak", model: [hierarchyBreakInstance: hierarchyBreakInstance,json:json]);
//render json;
Assuming that you are doing a request with some parameters, and need to return if was succesfull or not, and the data to fill the table with ajax.
I will do on that way, use the statuses of the HTTP to mark if it was a problem with the validation(normally we return 400 Bad Request and the message)
Example :
return ErrorSender.sendBadRequest("error validating field $field with value $value")
And the errorsender has a sendBadRequest method
[response: ['message': message, error: "bad_request", status: 400, cause: []], status: 400]
If the request was OK, you only need to respond the data with something like
return [response: results, status: 200]
In the client side you have to have one function if the request was OK to parse result, and one function if request have some validated data problem, database problem or whatever that caused that the request didnĀ“t return a 200(in the example),there are more status codes, you can check on
http://en.wikipedia.org/wiki/List_of_HTTP_status_codes
PD: Initial validation should be done on client side.
I have a client makes file upload request via dojo.io.iframe to pass a binary data to a web application running on websphere app server and the servlet class inside of the web app makes a rest web service call to an external system to pass the binary data. So there are three layers involved.
The problem I am having is trying to display returned json data which contains exact exception happened in the last layer after making rest web service call back to the client.
The client html page looks like this
<form id="myForm" method="post" enctype="multipart/form-data">
<div id="output"></div>
<input id="filename" type="file" name="filename" />
<input id="submitButton" type="submit" value="Submit"></input>
</form>
The client javascript looks like this I am having trouble in printing out RuntimeException caught in a servlet to a client.
require(["dojo/io/iframe","dojo/dom","dojo/on","dojo/dom-construct","dojo/domReaddy!"],function(iframe,dom,on,domConst) {
on(dom.byId("submitButton"),"click",function() {
iframe.send({
form: "myForm",
handleAs: "json",
url: "/rootContext/myServlet"
}).then(function(data) {
domConst.place("<p>" + data + "</p>","output");
}, function(err) {
domConst.place("<p>" + err + "</p>","output"); // hope to print out exception caught in third layer
});
});
});
Servlet looks like this.
protected void doPost(HttpServletRequest request, HttpServletResponse response) {
....
ServletOutputStream sos = null;
....
try {
domSomething(payLoad);
} catch (RuntimeException e) [
sos = response.getOutputStream();
sos.print(e.getMessage());
}
}
private void doSomething(String payLoad) {
URL url = null;
HttpURLConnection conn = null;
OutputStream os = null;
resource = new URL("someWhere");
conn = (HttpURLConnection) resource.openConnection();
conn.setDoOutput(true);
conn.setRequestMethod("POST");
os = conn.getOutputStream();
os.write(payLoad.getBytes());
os.close();
if (conn.getResponseCode() != HttpURLConnection.HTTP_CREATED) {
String retMsg = null;
StringBuilder sb = new StringBuilder();
BufferedReader br = new BufferedReader(new InputStreamReader(conn.getErrorStream()));
while ((retMsg = br.readLine()) != null) {
sb.append(retMsg);
}
br.close();
throw new RuntimeException(sb.toString()); // throws JSON format data
}
The servlet class makes rest web service call to an external system and if uploaded file data transmission fails it returns exception in json to the servlet class and I was trying to get that error data back to a client. This servlet class works fine for file uploading and if a corrupted file is uploaded then exception is generated. I didn't include logging mechanism in here, but it is implemented so that there is a log file in the app server that registers data transmitted included returned exception.
I am new to Dojo and having trouble using iframe api to display json data passed by a servlet class. I'd appreciate your advice on this matter. Thank you!
first of all I'd appreciate others who have contributed ideas to my question. The problem I was having fixed. I had to do following steps.
In the servlet class, wrap json data by html/body/textarea tags
From client side javascript, set handleAs: "json"
function(data) will be invoked and data would be json object so call whatever property name via . then mapping value will be printed out
Came to right solution via many trials/errors. One of the mistake I made was I used wrong slash for closing textarea tag by mistake in the servlet class.
In an application I am developing RESTful API and we want the client to send data as JSON. Part of this application requires the client to upload a file (usually an image) as well as information about the image.
I'm having a hard time tracking down how this happens in a single request. Is it possible to Base64 the file data into a JSON string? Am I going to need to perform 2 posts to the server? Should I not be using JSON for this?
As a side note, we're using Grails on the backend and these services are accessed by native mobile clients (iPhone, Android, etc), if any of that makes a difference.
I asked a similar question here:
How do I upload a file with metadata using a REST web service?
You basically have three choices:
Base64 encode the file, at the expense of increasing the data size by around 33%, and add processing overhead in both the server and the client for encoding/decoding.
Send the file first in a multipart/form-data POST, and return an ID to the client. The client then sends the metadata with the ID, and the server re-associates the file and the metadata.
Send the metadata first, and return an ID to the client. The client then sends the file with the ID, and the server re-associates the file and the metadata.
You can send the file and data over in one request using the multipart/form-data content type:
In many applications, it is possible for a user to be presented with
a form. The user will fill out the form, including information that
is typed, generated by user input, or included from files that the
user has selected. When the form is filled out, the data from the
form is sent from the user to the receiving application.
The definition of MultiPart/Form-Data is derived from one of those
applications...
From http://www.faqs.org/rfcs/rfc2388.html:
"multipart/form-data" contains a series of parts. Each part is
expected to contain a content-disposition header [RFC 2183] where the
disposition type is "form-data", and where the disposition contains
an (additional) parameter of "name", where the value of that
parameter is the original field name in the form. For example, a part
might contain a header:
Content-Disposition: form-data; name="user"
with the value corresponding to the entry of the "user" field.
You can include file information or field information within each section between boundaries. I've successfully implemented a RESTful service that required the user to submit both data and a form, and multipart/form-data worked perfectly. The service was built using Java/Spring, and the client was using C#, so unfortunately I don't have any Grails examples to give you concerning how to set up the service. You don't need to use JSON in this case since each "form-data" section provides you a place to specify the name of the parameter and its value.
The good thing about using multipart/form-data is that you're using HTTP-defined headers, so you're sticking with the REST philosophy of using existing HTTP tools to create your service.
I know that this thread is quite old, however, I am missing here one option. If you have metadata (in any format) that you want to send along with the data to upload, you can make a single multipart/related request.
The Multipart/Related media type is intended for compound objects consisting of several inter-related body parts.
You can check RFC 2387 specification for more in-depth details.
Basically each part of such a request can have content with different type and all parts are somehow related (e.g. an image and it metadata). The parts are identified by a boundary string, and the final boundary string is followed by two hyphens.
Example:
POST /upload HTTP/1.1
Host: www.hostname.com
Content-Type: multipart/related; boundary=xyz
Content-Length: [actual-content-length]
--xyz
Content-Type: application/json; charset=UTF-8
{
"name": "Sample image",
"desc": "...",
...
}
--xyz
Content-Type: image/jpeg
[image data]
[image data]
[image data]
...
--foo_bar_baz--
Here is my approach API (i use example) - as you can see, you I don't use any file_id (uploaded file identifier to the server) in API:
Create photo object on server:
POST: /projects/{project_id}/photos
body: { name: "some_schema.jpg", comment: "blah"}
response: photo_id
Upload file (note that file is in singular form because it is only one per photo):
POST: /projects/{project_id}/photos/{photo_id}/file
body: file to upload
response: -
And then for instance:
Read photos list
GET: /projects/{project_id}/photos
response: [ photo, photo, photo, ... ] (array of objects)
Read some photo details
GET: /projects/{project_id}/photos/{photo_id}
response: { id: 666, name: 'some_schema.jpg', comment:'blah'} (photo object)
Read photo file
GET: /projects/{project_id}/photos/{photo_id}/file
response: file content
So the conclusion is that, first you create an object (photo) by POST, and then you send second request with the file (again POST). To not have problems with CACHE in this approach we assume that we can only delete old photos and add new - no update binary photo files (because new binary file is in fact... NEW photo). However if you need to be able to update binary files and cache them, then in point 4 return also fileId and change 5 to GET: /projects/{project_id}/photos/{photo_id}/files/{fileId}.
I know this question is old, but in the last days I had searched whole web to solution this same question. I have grails REST webservices and iPhone Client that send pictures, title and description.
I don't know if my approach is the best, but is so easy and simple.
I take a picture using the UIImagePickerController and send to server the NSData using the header tags of request to send the picture's data.
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:[NSURL URLWithString:#"myServerAddress"]];
[request setHTTPMethod:#"POST"];
[request setHTTPBody:UIImageJPEGRepresentation(picture, 0.5)];
[request setValue:#"image/jpeg" forHTTPHeaderField:#"Content-Type"];
[request setValue:#"myPhotoTitle" forHTTPHeaderField:#"Photo-Title"];
[request setValue:#"myPhotoDescription" forHTTPHeaderField:#"Photo-Description"];
NSURLResponse *response;
NSError *error;
[NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error];
At the server side, I receive the photo using the code:
InputStream is = request.inputStream
def receivedPhotoFile = (IOUtils.toByteArray(is))
def photo = new Photo()
photo.photoFile = receivedPhotoFile //photoFile is a transient attribute
photo.title = request.getHeader("Photo-Title")
photo.description = request.getHeader("Photo-Description")
photo.imageURL = "temp"
if (photo.save()) {
File saveLocation = grailsAttributes.getApplicationContext().getResource(File.separator + "images").getFile()
saveLocation.mkdirs()
File tempFile = File.createTempFile("photo", ".jpg", saveLocation)
photo.imageURL = saveLocation.getName() + "/" + tempFile.getName()
tempFile.append(photo.photoFile);
} else {
println("Error")
}
I don't know if I have problems in future, but now is working fine in production environment.
FormData Objects: Upload Files Using Ajax
XMLHttpRequest Level 2 adds support for the new FormData interface.
FormData objects provide a way to easily construct a set of key/value pairs representing form fields and their values, which can then be easily sent using the XMLHttpRequest send() method.
function AjaxFileUpload() {
var file = document.getElementById("files");
//var file = fileInput;
var fd = new FormData();
fd.append("imageFileData", file);
var xhr = new XMLHttpRequest();
xhr.open("POST", '/ws/fileUpload.do');
xhr.onreadystatechange = function () {
if (xhr.readyState == 4) {
alert('success');
}
else if (uploadResult == 'success')
alert('error');
};
xhr.send(fd);
}
https://developer.mozilla.org/en-US/docs/Web/API/FormData
Since the only missing example is the ANDROID example, I'll add it.
This technique uses a custom AsyncTask that should be declared inside your Activity class.
private class UploadFile extends AsyncTask<Void, Integer, String> {
#Override
protected void onPreExecute() {
// set a status bar or show a dialog to the user here
super.onPreExecute();
}
#Override
protected void onProgressUpdate(Integer... progress) {
// progress[0] is the current status (e.g. 10%)
// here you can update the user interface with the current status
}
#Override
protected String doInBackground(Void... params) {
return uploadFile();
}
private String uploadFile() {
String responseString = null;
HttpClient httpClient = new DefaultHttpClient();
HttpPost httpPost = new HttpPost("http://example.com/upload-file");
try {
AndroidMultiPartEntity ampEntity = new AndroidMultiPartEntity(
new ProgressListener() {
#Override
public void transferred(long num) {
// this trigger the progressUpdate event
publishProgress((int) ((num / (float) totalSize) * 100));
}
});
File myFile = new File("/my/image/path/example.jpg");
ampEntity.addPart("fileFieldName", new FileBody(myFile));
totalSize = ampEntity.getContentLength();
httpPost.setEntity(ampEntity);
// Making server call
HttpResponse httpResponse = httpClient.execute(httpPost);
HttpEntity httpEntity = httpResponse.getEntity();
int statusCode = httpResponse.getStatusLine().getStatusCode();
if (statusCode == 200) {
responseString = EntityUtils.toString(httpEntity);
} else {
responseString = "Error, http status: "
+ statusCode;
}
} catch (Exception e) {
responseString = e.getMessage();
}
return responseString;
}
#Override
protected void onPostExecute(String result) {
// if you want update the user interface with upload result
super.onPostExecute(result);
}
}
So, when you want to upload your file just call:
new UploadFile().execute();
I wanted send some strings to backend server. I didnt use json with multipart, I have used request params.
#RequestMapping(value = "/upload", method = RequestMethod.POST)
public void uploadFile(HttpServletRequest request,
HttpServletResponse response, #RequestParam("uuid") String uuid,
#RequestParam("type") DocType type,
#RequestParam("file") MultipartFile uploadfile)
Url would look like
http://localhost:8080/file/upload?uuid=46f073d0&type=PASSPORT
I am passing two params (uuid and type) along with file upload.
Hope this will help who don't have the complex json data to send.
You could try using https://square.github.io/okhttp/ library.
You can set the request body to multipart and then add the file and json objects separately like so:
MultipartBody requestBody = new MultipartBody.Builder()
.setType(MultipartBody.FORM)
.addFormDataPart("uploadFile", uploadFile.getName(), okhttp3.RequestBody.create(uploadFile, MediaType.parse("image/png")))
.addFormDataPart("file metadata", json)
.build();
Request request = new Request.Builder()
.url("https://uploadurl.com/uploadFile")
.post(requestBody)
.build();
try (Response response = client.newCall(request).execute()) {
if (!response.isSuccessful()) throw new IOException("Unexpected code " + response);
logger.info(response.body().string());
#RequestMapping(value = "/uploadImageJson", method = RequestMethod.POST)
public #ResponseBody Object jsongStrImage(#RequestParam(value="image") MultipartFile image, #RequestParam String jsonStr) {
-- use com.fasterxml.jackson.databind.ObjectMapper convert Json String to Object
}
Please ensure that you have following import. Ofcourse other standard imports
import org.springframework.core.io.FileSystemResource
void uploadzipFiles(String token) {
RestBuilder rest = new RestBuilder(connectTimeout:10000, readTimeout:20000)
def zipFile = new File("testdata.zip")
def Id = "001G00000"
MultiValueMap<String, String> form = new LinkedMultiValueMap<String, String>()
form.add("id", id)
form.add('file',new FileSystemResource(zipFile))
def urld ='''http://URL''';
def resp = rest.post(urld) {
header('X-Auth-Token', clientSecret)
contentType "multipart/form-data"
body(form)
}
println "resp::"+resp
println "resp::"+resp.text
println "resp::"+resp.headers
println "resp::"+resp.body
println "resp::"+resp.status
}