RESTful webservice using Spring mvc respond back with data file as response - web-services

How can i respond back with a text file containing json data upon request from client .
The request url is:
http://localhost:8082/web/ws/datafileid/json/Sat May 16 12:05:07 IST 2015.txt/
Controller code that handles the request is:
#RequestMapping(value=EmpRestURIConstants.DATAFILE_REQUEST,method=RequestMethod.GET)
#ResponseBody
public String datafileresponse(#PathVariable("filename") String filename, HttpServletResponse response) {
return cinehomeRestService.checkfilevalid(filename);
}
Service class that handles the request to check the file exists is:
#Override
public String checkfilevalid(String filename) {
String datafilename=webServiceDao.getdatafilename();
JSONObject obj = new JSONObject();
if(datafilename.equals(filename)) {
return "file";
}
else {
try {
obj.put("status", "022");
} catch (JSONException e) {
e.printStackTrace();
}
return obj.toString();
}
}
Here I need to respond back with the datafile.txt that exists at location resources. How can I perform the task. Can anyone help?
i have tried a method
#RequestMapping(value=EmpRestURIConstants.DATAFILE_REQUEST,method=RequestMethod.GET,produces=MediaType.APPLICATION_JSON_VALUE)
public #ResponseBody Response datafileresponse(#PathVariable("filename")String filename) throws IOException{
JSONObject readdata = new JSONObject();
String uploadPath = servletContext.getRealPath("");
String fullyqualifiedfilename=uploadPath+filename;
System.out.println("+++++++++"+fullyqualifiedfilename);
return Response.ok(uploadPath)
.header("Content-Disposition", "attachment; filename=\"" + fullyqualifiedfilename + "\"" ) //optional
.build();
}
i GOT THE REPLY AS...
{ "statusType": "OK", "entity": /home/cine/WORKSPACES/study/.metadata/.plugins/org.eclipse.wst.server.‌​core/tmp0/wtpwebapps/
"entityType": "java.lang.String", "metadata": { "Content-Disposition": [ "attachment;
filename="/home/cine/WORKSPACES/study/.metadata/.plugins/org.eclipse.wst.server.‌​core/tmp0/wtpwebapps/Cine Sat May 16 12:05:07 IST 2015.txt"" ] }, "status": 200 }
What this status means. Does the client can fetch teh file using this response.??

Related

AppSync Java authenticate with IAM

I am trying to update my appsync client to authenticate with IAM credentials. In case of API_KEY I set the API_KEY_HEADER like so: request.addHeader(API_KEY_HEADER, this.apiKey); Is there a similar way to authenticate in a Java client with IAM credentials? Is there a header I can pass in to pass in the secret and access keys like here: https://docs.amplify.aws/lib/graphqlapi/authz/q/platform/js#iam? Or should I just be using a cognito user pool as a way to authenticate the request?
According to AWS Documentation we need to use sign requests using the process documented here: https://docs.aws.amazon.com/general/latest/gr/signature-version-4.html and steps listed here: https://docs.aws.amazon.com/general/latest/gr/sigv4_signing.html.
I also found an implementation here: https://medium.com/#tridibbolar/aws-lambda-as-an-appsync-client-fbb0c1ce927d. Using the code above:
private void signRequest(final Request<AmazonWebServiceRequest> request) {
final AWS4Signer signer = new AWS4Signer();
signer.setRegionName(this.region);
signer.setServiceName("appsync");
signer.sign(request, this.appsyncCredentials);
}
private Request<AmazonWebServiceRequest> getRequest(final String data) {
final Request<AmazonWebServiceRequest> request =
new DefaultRequest<AmazonWebServiceRequest>("appsync");
request.setHttpMethod(HttpMethodName.POST);
request.setEndpoint(URI.create(this.appSyncEndpoint));
final byte[] byteArray = data.getBytes(Charset.forName("UTF-8"));
request.setContent(new ByteArrayInputStream(byteArray));
request.addHeader(AUTH_TYPE_HEADER, AWS_IAM_AUTH_TYPE);
request.addHeader(HttpHeaders.CONTENT_TYPE, APPLICATION_GRAPHQL);
request.addHeader(HttpHeaders.CONTENT_LENGTH, String.valueOf(byteArray.length));
signRequest(request);
return request;
}
private HttpResponseHandler<String> getResponseHandler() {
final HttpResponseHandler<String> responseHandler = new HttpResponseHandler<String>() {
#Override
public String handle(com.amazonaws.http.HttpResponse httpResponse) throws Exception {
final String result = IOUtils.toString(httpResponse.getContent());
if(httpResponse.getStatusCode() != HttpStatus.SC_OK) {
final String errorText = String.format(
"Error posting request. Response status code was %s and text was %s. ",
httpResponse.getStatusCode(),
httpResponse.getStatusText());
throw new RuntimeException(errorText);
} else {
final ObjectMapper objectMapper = new ObjectMapper();
//custom class to parse appsync response.
final AppsyncResponse response = objectMapper.readValue(result, AppsyncResponse.class);
if(CollectionUtils.isNotEmpty(response.getErrors())){
final String errorMessages = response
.getErrors()
.stream()
.map(Error::getMessage)
.collect(Collectors.joining("\n"));
final String errorText = String.format(
"Error posting appsync request. Errors were %s. ",
errorMessages);
throw new RuntimeException(errorText);
}
}
return result;
}
#Override
public boolean needsConnectionLeftOpen() {
return false;
}
};
return responseHandler;
}
private Response<String> makeGraphQlRequest(final Request<AmazonWebServiceRequest> request) {
return this.httpClient.requestExecutionBuilder()
.executionContext(new ExecutionContext())
.request(request)
.execute(getResponseHandler());
}

How to do http request for POST methord (rest api url created by aws apigateway) from android using volly

How to send a proper http request from android using volly for a post REST URL created with using aws api gateway?
How to make a proper http request from android so that these values accept by api gateway.
Api gateway internal testing works properly.
This is the parameter need to pass through the request.
{
"id": "22",
"res": "10",
"rate": "75",
"index": "1"
}
//this method is used call http request
public static void newPost2(Context context){
String awsAccessKey = "awsAccessKey";
final String awsSecretKey = "awsSecretKey";
String dateStr = ClientSSLSocketFactory.getServerTime();
String scope = dateStr + "/us-east-1/execute-api/aws4_request,";
String headerNames = "host;x-amz-date";
final String credentialsAuthorizationHeader = "Credential=" + awsAccessKey + "/" + scope;
String signedHeadersAuthorizationHeader = "SignedHeaders=" + headerNames;
String signatureAuthorizationHeader = "Signature=" + "hex encoded signature";
final String authorization = "AWS4-HMAC-SHA256 "
+ credentialsAuthorizationHeader + ", "
+ signedHeadersAuthorizationHeader + ", "
+ signatureAuthorizationHeader;
final String url="https://xxxxxxx2.execute-api.us-east-1.amazoxxxxxxxxxxxxxxxx";
RequestQueue queue = Volley.newRequestQueue(context);
StringRequest sr = new StringRequest(Request.Method.POST,url, new Response.Listener<String>() {
#Override
public void onResponse(String response) {
// mPostCommentResponse.requestCompleted();
System.out.print("\n\n\n......post ok."+response);
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
// mPostCommentResponse.requestEndedWithError(error);
System.out.print("\n\n\n.......post error."+error);
error.printStackTrace();
}
}){
#Override
protected Map<String,String> getParams(){
Map<String,String> params = new HashMap<String, String>();
// params.put("Content-Type", "application/json; charset=utf-8");
params.put("id","22");
params.put("rate","10");
params.put("res", "75");
params.put("index","1");
return params;
}
#Override
public Map<String, String> getHeaders() throws AuthFailureError {
Map<String,String> params = new HashMap<String, String>();
// params.put("Content-Type","application/x-www-form-urlencoded");
params.put("Host", "apigateway.us-east-1.amazonaws.com");
params.put("x-amz-date", ClientSSLSocketFactory.getawsnettime());
params.put("Authorization", authorization);
params.put("Content-Type", "application/x-amz-json-1.0");
return params;
}
};
queue.add(sr);
}
but shows error in log
...stringr..header......post error.com.android.volley.AuthFailureError
11-30 14:52:14.140 4663-4663/com.example.acernrc.noveleven W/System.err: com.android.volley.ServerError
11-30 14:52:14.140 4663-4663/com.example.acernrc.noveleven W/System.err: at com.android.volley.toolbox.BasicNetwork.performRequest(BasicNetwork.java:163)

Spring MVC File Upload with multipart data and unit test

I am using Spring 4 latest, and I generally have no problem writing RESTful controllers. There is a legacy web-app, which is using java.net.HTTPUrlConnection to do a multi-part upload. There are 3 pieces of data we are uploading:
1 is a PDF file, and we have the bytes, then the other two pieces of data are just 2 string fields.
First let me show you the Spring REST controller to accept the data:
#RequestMapping(value = "/save", method = RequestMethod.POST, produces = "application/json", consumes = "multipart/form-data")
public #ResponseBody boolean saveData(#RequestPart(value = "field1") String field1, #RequestPart(value = "field2") String field2, #RequestParam(value = "pdfbytes") String pdfbytes)
{
System.out.println("saveData: field1=" + field1);
System.out.println("saveData: field2=" + field2);
System.out.println("saveData: pdfbytes=" + pdfbytes);
boolean response = true;
return response;
}
The code in front-end, for sending the data using 'java.net.HttpURLConnection'
looks like this:
String boundary = MultiPartFormOutputStream.createBoundary();
URL uploadDocumentUrl = new URL(protocol + "://" + host + UPLOAD_EDITED_DOCUMENT);
HttpURLConnection urlConn = (HttpURLConnection) MultiPartFormOutputStream.createConnection(uploadDocumentUrl);
urlConn.setRequestProperty("Content-Type", MultiPartFormOutputStream.getContentType(boundary));
urlConn.setRequestProperty("Connection", "Keep-Alive");
urlConn.setRequestProperty("Cache-Control", "no-cache");
urlConn.setRequestProperty("User-Agent", userAgent);
urlConn.setRequestMethod("POST");
MultiPartFormOutputStream out = new MultiPartFormOutputStream(urlConn.getOutputStream(), boundary);
String pdfbytes= getEncodedDocument(pdf);
out.writeField("field1", field1);
out.writeField("field2", field2);
out.writeField("pdfbytes", pdfbytes);
out.close();
int responseCode = urlConn.getResponseCode();
String responseMessage = urlConn.getResponseMessage();
"MultiPartFormOutputStream" is a custom object that was created to send data via HttpUrlConnection, it's pretty standard code. I do trust it at this time.
So, based on how we are sending the data, do I need to change the Controller to do anything different, or does that look ok?
Now here is the code, that I am using to Unit Test that controller:
#Test
public void testMockUpload() throws Exception
{
// Load resource being uploaded
byte[] pdfbytes = getByteArrayFromFile(FILENAME);
MockMultipartFile firstFile = new MockMultipartFile("field1", "", "text/plain", "field1 data".getBytes());
MockMultipartFile secondFile = new MockMultipartFile("field2", "", "text/plain", "field2 data".getBytes());
MockMultipartFile jsonFile = new MockMultipartFile("pdfbytes", "", "text/plain", pdfbytes);
MockHttpServletRequestBuilder requestBuilder = MockMvcRequestBuilders.fileUpload(BASE_URL + "/save").file(firstFile).file(secondFile).file(jsonFile)
.with(user(USERNAME).roles("role1", "role2")).contentType(MediaType.MULTIPART_FORM_DATA_VALUE);
this.mockMvc.perform(requestBuilder).andDo(print()).andExpect(status().isOk());
}
And the error I get back now, is:
org.springframework.web.method.annotation.MethodArgumentConversionNotSupportedException
which I am looking into. If I need to make any changes on how I need to create my test, I am very open to that. Eventually, I will get everything to sync up between the sending code, the receiving controller, and the unit test.
Thanks in advance! As usual, if there is any other data, or information, I can provide, please let me know. Thanks!
To upload one file you would define the RequestParam type as org.springframework.web.multipart.MultipartFile;
#RequestMapping(value = "/save", method = RequestMethod.POST, produces = "application/json", consumes = "multipart/form-data")
public #ResponseBody boolean saveData(#RequestParam(value = "file") MultipartFile file)
{
return response;
}
For Multiple files I'd try creating a Wrapper form:
public class UploadForm{
private List<MultipartFile> files;
}
Bind to this in the controller:
#RequestMapping(value = "/save", method = RequestMethod.POST, produces = "application/json", consumes = "multipart/form-data")
public #ResponseBody boolean saveData(#ModelAttribute uploadForm)
{
return response;
}
and then use Spring's support for indexed fields to bind to a collection:
Test:
MockMultipartFile firstFile = new MockMultipartFile("files[0]", "", "text/plain", "field1 data".getBytes());
MockMultipartFile secondFile = new MockMultipartFile("files[1]", "", "text/plain", "field2 data".getBytes());
MockMultipartFile jsonFile = new MockMultipartFile("files[2]", "", "text/plain", pdfbytes);
Client:
out.writeField("files[0]", file1Bytes);
out.writeField("files[1]", file2Bytes);
...

Java RESTEasy WebService - Download the image file from HTTPResponse object.

I need to download a image files from the file system using RESTEasy web service and the input httpclient is JSON and the output response is
#Produces({"image/jpeg,image/png"})
Here is my client code:
public void getFileDownload(){
log("inside getServerPath....");
DefaultHttpClient httpClient = new DefaultHttpClient();
HttpPost httpPost = new HttpPost(downloadWebService_URL);
JSONObject json = new JSONObject();
json.put("filePath", "/ngs/app/sample.png");
json.put("fileName", "sample.png");
log("json-->"+json.toString());
StringEntity inputJson = null;
try {
inputJson = new StringEntity(json.toString());
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
log("inputJson = " + inputJson.toString());
inputJson.setContentType("application/json");
httpPost.setEntity(inputJson);
httpPost.addHeader("AppType", "TC");
log("httpPost... httpPost");
HttpResponse response = null;
try {
response = httpClient.execute(httpPost);
log("response:-->"+response);
}
catch (ClientProtocolException e) {
e.printStackTrace();
}
catch (IOException e) {
e.printStackTrace();
}
catch (Exception e)
{
log("E:: " + ExceptionUtils.getStackTrace(e));
}
}
Here is my Webservice code:
#Path("/downloadservice")
public class DownloadFileWS {
private static final String FILE_PATH = "/ngs/app/sample.png";
#POST
// #Path("/images")
#Path("/{fileName}/images")
#Consumes({"application/json"})
#Produces({"image/jpeg,image/png"})
public Response getImageFile(#PathParam("fileName") String fileName) {
File file = new File(FILE_PATH);
System.out.println("File requested is : " + fileName);
Logger.getLogger("!!!!!!!!!!!"+FILE_PATH);
System.out.println("########"+FILE_PATH);
ResponseBuilder response = Response.ok((Object) file);
response.header("Content-Disposition","attachment; filename=\"sample.png\"");
return response.build();
}
The HTTP Response is:
response:-->HTTP/1.1 200 OK [Date: Tue, 19 Jul 2016 00:36:22 GMT,
Content-Length: 6192, Content-Type: image/png, Content-Disposition:
attachment; filename="sample.png", X-Powered-By: Servlet/2.5 JSP/2.1]
org.apache.http.conn.BasicManagedEntity#2ace1307
Question:
1. Based on the response, it looks like the service is sending the image in HTTPResponse object. May i know how to download the image received from HTTP Response?
2. The requirement is to click a link which calls the webservice by passing JSON as input request and the image should automatically download to the user's local machine browser.

IME media type application/pdf was not found in restful webservice

I've got this below restful webservice code. But when the webservice is accessed I'm getting "MIME media type application/pdf was not found". The docService.findByVersionId does return a "TestDoc" which holds the pdf content as byte[].
Can you please help me in fixing this problem?
#GET
#Path("/getPdf/{versionId}")
#Produces("application/pdf")
public Response getPdfFile(#PathParam("versionId") final String versionId) {
try {
final TestDoc doc = this.docService.findByVersionId(versionId);
final ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
final BufferedOutputStream bos = new BufferedOutputStream(byteArrayOutputStream);
final byte[] pdfContent = doc.getPdfDoc();
bos.write(pdfContent);
bos.flush();
bos.close();
return Response.ok(byteArrayOutputStream).build();
} catch (IOException e) {
e.printStackTrace();
return null;
}
}
error:
Exception:
2014-01-02 12:42:07,497 ERROR [STDERR] 02-Jan-2014 12:42:07 com.sun.jersey.spi.container.ContainerResponse write
SEVERE: A message body writer for Java class java.io.ByteArrayOutputStream, and Java type class java.io.ByteArrayOutputStream, and MIME media type application/pdf was not found
It seems that you can't use the ByteArrayOutputStream. The solution is to use StreamingOutput.
#GET
public Response generatePDF(String content) {
try {
ByteArrayOutputStream outputStream = service.generatePDF(content);
StreamingOutput streamingOutput = getStreamingOutput(outputStream);
Response.ResponseBuilder responseBuilder = Response.ok(streamingOutput, "application/pdf");
responseBuilder.header("Content-Disposition", "attachment; filename=Filename.pdf");
return responseBuilder.build();
} catch (IOException e) {
log.log(Level.SEVERE, e.getMessage(), e);
return Response.serverError().build();
}
}
private StreamingOutput getStreamingOutput(final ByteArrayOutputStream byteArrayOutputStream) {
return new StreamingOutput() {
public void write(OutputStream output) throws IOException, WebApplicationException {
byteArrayOutputStream.writeTo(output);
}
};
}