error uploading file HTTP Client & RESTful server - rest

I'm trying to create a HTTP Client to upload a file following this example: http://java.dzone.com/articles/file-upload-apache-httpclient
When I run the application to upload the file on my RESTFul service, I get:
HTTP ERROR 500
Problem accessing /file/upload. Reason:
Server ErrorCaused by:java.lang.NullPointerException
at com.nice.rest.UploadFileService.uploadFile(UploadFileService.java:33)
...
Where line 33 is:
public class UploadFileService {
#POST
#Path("/upload")
#Consumes(MediaType.MULTIPART_FORM_DATA)
public Response uploadFile(
#FormDataParam("file") InputStream uploadedInputStream,
#FormDataParam("file") FormDataContentDisposition fileDetail) {
//line 33: String uploadedFileLocation = "/mnt/folder/"+ fileDetail.getFileName();
System.out.println("uploadedFileLocation : "+uploadedFileLocation);
// save it
writeToFile(uploadedInputStream, uploadedFileLocation);
String output = "200 OK<br />" + uploadedFileLocation;
return Response.status(200).entity(output).build();
}
Surprisingly, when I upload a file using a html form it works fine:
form action="http://X.X.X.X:8080/file/upload" method="post" enctype="multipart/form-data"
What's wrong?
thanks!!

When you build your multi-part entity, make sure that the #FormDataParam annotation value contains the name of the part within the multipart.
It looks like the part you're looking for doesn't exist hence the NullPointerException.
Please post your client code if possible showing how you construct the multi-part entity

Related

Vertx Web Client throwing HTTP 415 Unsupported Media Type for Multipart/form-data

This service receives the multipart request from mobile client and passes on the request to downstream service for uploading the image. I am seeing 415 Unsupported Media Type in my downstream service
private void makeRequest(HttpRequest<Buffer> httpRequest,
Promise<Object> future,
RequestContext requestContext,
RoutingContext routingContext,
Entry entry) {
MultipartForm multipartForm = MultipartForm.create();
MultiMap attributes = routingContext.request()
.formAttributes();
attributes.forEach(attribute -> {
multipartForm.attribute(attribute.getKey(), attribute.getValue());
});
routingContext.fileUploads()
.forEach(fileUpload -> {
multipartForm.binaryFileUpload(fileUpload.name(), fileUpload.fileName(),
fileUpload.uploadedFileName(), fileUpload.contentType());
});
httpRequest.sendMultipartForm(multipartForm, response -> {
handleResponse(routingContext, future, response, requestContext, entry);
});
}
Getting the below exception
javax.ws.rs.NotSupportedException: HTTP 415 Unsupported Media Type
at org.glassfish.jersey.server.internal.routing.MethodSelectingRouter.getMethodRouter(MethodSelectingRouter.java:478)
at org.glassfish.jersey.server.internal.routing.MethodSelectingRouter.access$000(MethodSelectingRouter.java:94)
at org.glassfish.jersey.server.internal.routing.MethodSelectingRouter$4.apply(MethodSelectingRouter.java:779)
at org.glassfish.jersey.server.internal.routing.MethodSelectingRouter.apply(MethodSelectingRouter.java:371)
API signature of my downstream service
#POST
#Timed
#Path("{userId}/{scope}/upload")
#Consumes(MediaType.MULTIPART_FORM_DATA)
#Produces(MediaType.APPLICATION_JSON)
#ApiOperation("Multipart upload of an image")
Can someone please guide what is wrong in my code snippet or is there any setting which needs to be enabled in vertx server or vertx web client?
Thanks,
Nitish Goyal
I was able to resolve this by explicitly setting the header
.putHeader("content-type", "multipart/form-data")

How to make a RESTful call using Basic Authentication in apache camel?

I have an apache camel application that requires sending log files to an endpoint and this requires Basic Authentication. I was able to pass the authMethod, authusername and authPassword to the url as specified in the camel documentation but the challange I'm having is that I keep getting null response from the endpoint after starting the application.
However, the same endpoint returns response code and response body using postman.
Below is my code:
from("{{routes.feeds.working.directory}}?idempotent=true")
.process(new Processor() {
#Override
public void process(Exchange exchange) throws Exception {
MultipartEntityBuilder multipartEntityBuilder = MultipartEntityBuilder.create();
multipartEntityBuilder.setMode(HttpMultipartMode.BROWSER_COMPATIBLE);
String fileName = exchange.getIn().getHeader(Exchange.FILE_NAME, String.class);
File file = exchange.getIn().getBody(File.class);
multipartEntityBuilder.addPart("file",
new FileBody(file, ContentType.MULTIPART_FORM_DATA, fileName));
exchange.getOut().setBody(multipartEntityBuilder.build());
Message out = exchange.getOut();
int responseCode = out.getHeader(Exchange.HTTP_RESPONSE_CODE, Integer.class);
log.info("response code "+responseCode);
}
})
.setHeader(Exchange.HTTP_QUERY,
constant("authMethod=Basic&authUsername="+username+"&authPassword="+password+""))
.to(TARGET_WITH_AUTH +"/"+uuid+"/files")
.log(LoggingLevel.DEBUG, "response code >>>>"+Exchange.HTTP_RESPONSE_CODE)
.log(LoggingLevel.INFO, "RESPONSE BODY ${body}")
.end();
Kindly help review and advise further
For HTTP basic authentication I use this before sending a request
<setHeader headerName="Authorization">
<constant>Basic cm9vdDpyb290</constant>
</setHeader>
cm9vdDpyb290 - Encoded Base64 root:root(username and password) string
This was fixed by using httpClient to send my requests with Basic Authentication. Apparently, authMethod in apache camel doesn't send the credentials along with the Post Request and that's why I was getting the initial 401 response code.
Thank y'all for your contributions.

RESTful client in Unity - validation error

I have a RESTful server created with ASP.Net and am trying to connect to it with the use of a RESTful client from Unity. GET works perfectly, however I am getting a validation error when sending a POST request. At the same time both GET and POST work when sending requests from Postman.
My Server:
[HttpPost]
public IActionResult Create(User user){
Console.WriteLine("***POST***");
Console.WriteLine(user.Id+", "+user.sex+", "+user.age);
if(!ModelState.IsValid)
return BadRequest(ModelState);
_context.Users.Add(user);
_context.SaveChanges();
return CreatedAtRoute("GetUser", new { id = user.Id }, user);
}
My client:
IEnumerator PostRequest(string uri, User user){
string u = JsonUtility.ToJson(user);
Debug.Log(u);
using (UnityWebRequest webRequest = UnityWebRequest.Post(uri, u)){
webRequest.SetRequestHeader("Content-Type","application/json");
yield return webRequest.SendWebRequest();
string[] pages = uri.Split('/');
int page = pages.Length - 1;
if (webRequest.isNetworkError || webRequest.isHttpError){
Debug.Log(pages[page] + ":\nReceived: " + webRequest.downloadHandler.text);
}
else{
Debug.Log(pages[page] + ":\nReceived: " + webRequest.downloadHandler.text);
}
}
}
I was trying both with the Json conversion and writing the string on my own, also with the WWWForm, but the error stays.
The error says that it's an unknown HTTP error. When printing the returned text it says:
"One or more validation errors occurred.","status":400,"traceId":"|b95d39b7-4b773429a8f72b3c.","errors":{"$":["'%' is an invalid start of a value. Path: $ | LineNumber: 0 | BytePositionInLine: 0."]}}
On the server side it recognizes the correct method and controller, however, it doesn't even get to the first line of the method (Console.WriteLine). Then it says: "Executing ObjectResult, writing value of type 'Microsoft.AspNetCore.Mvc.ValidationProblemDetails'".
Here're all of the server side messages:
info: Microsoft.AspNetCore.Hosting.Diagnostics[1]
Request starting HTTP/1.1 POST http://localhost:5001/user application/json 53
info: Microsoft.AspNetCore.Routing.EndpointMiddleware[0]
Executing endpoint 'TheNewestDbConnect.Controllers.UserController.Create (TheNewestDbConnect)'
info: Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker[3]
Route matched with {action = "Create", controller = "User"}. Executing controller action with signature Microsoft.AspNetCore.Mvc.IActionResult Create(TheNewestDbConnect.Data.Entities.User) on controller TheNewestDbConnect.Controllers.UserController (TheNewestDbConnect).
info: Microsoft.AspNetCore.Mvc.Infrastructure.ObjectResultExecutor[1]
Executing ObjectResult, writing value of type 'Microsoft.AspNetCore.Mvc.ValidationProblemDetails'.
info: Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker[2]
Executed action TheNewestDbConnect.Controllers.UserController.Create (TheNewestDbConnect) in 6.680400000000001ms
info: Microsoft.AspNetCore.Routing.EndpointMiddleware[1]
Executed endpoint 'TheNewestDbConnect.Controllers.UserController.Create (TheNewestDbConnect)'
info: Microsoft.AspNetCore.Hosting.Diagnostics[2]
Request finished in 11.3971ms 400 application/problem+json; charset=utf-8
info: Microsoft.AspNetCore.Hosting.Diagnostics[1]
I have no idea what is happening and how to solve it. Any help will be strongly appreciated!
Turned out I was just missing an upload handler. Adding this line solved it: webRequest.uploadHandler = new UploadHandlerRaw(System.Text.Encoding.UTF8.GetBytes(JsonObject));

How to retrieve fault information from soap error response using script in SoapUI mock service

I created a mock service in SoapUI. I am using Groovy in this mock service so I can mock some requests, as well as forward other requests to the actual web service I am mocking.
When the web service returns one of three possible fault messages, I am unable to retrieve that actual fault from the soap response.
The mock service Groovy script just replies with the response herebelow (IOException, http status 500).
But when sending a request to the actual web service directly, I get the response I actually would like to get.
Groovy code which forwards the request and retrieve a response:
def soapUrl = new URL("[actual web service]");
def connection = soapUrl.openConnection();
connection.setRequestMethod("POST");
connection.setRequestProperty("Content-Type" ,"text/html");
connection.setRequestProperty("SOAPAction", "");
connection.doOutput = true;
Writer writer = new OutputStreamWriter(connection.outputStream);
writer.write(soapRequest);
writer.flush();
writer.close();
connection.connect();
def soapResponse = connection.content.text;
// alert.showInfoMessage(soapResponse);
requestContext.responseMessage = soapResponse;
Response using the Groovy scripted mock service:
<soapenv:Body>
<soapenv:Fault>
<faultcode>Server</faultcode>
<faultstring>Failed to dispatch using script; java.io.IOException: Server returned HTTP response code: 500 for URL: [the endpoint url]</faultstring>
</soapenv:Fault>
</soapenv:Body>
</soapenv:Envelope>
Response when accessing the web service directly (with the same request):
<soapenv:Body>
<soapenv:Fault>
<faultcode>soapenv:Server</faultcode>
<faultstring> [actual fault message] </faultstring>
<detail> [useful details about the fault] </detail>
</soapenv:Fault>
</soapenv:Body>
</soapenv:Envelope>
When using the script, why is the response not the same as if I would retrieve it directly?
Ok I found out I can use the connection (URLConnection) in a different way.
I made some changes based on the accepted answer here.
Now, the actual response, happy or error, is retrieved. So in both cases the web service response is being forwarded to the mock service output. And now I can see the fault info in the response.
...
connection.connect();
// Get the response
HttpURLConnection httpConnection = (HttpURLConnection) connection;
InputStream is;
if (httpConnection.getResponseCode() < HttpURLConnection.HTTP_BAD_REQUEST) {
is = httpConnection.getInputStream();
} else {
// Http error
is = httpConnection.getErrorStream();
}
// Read from input stream
StringBuilder builder = new StringBuilder();
BufferedReader buffer = new BufferedReader(new InputStreamReader(is));
String line;
while ((line = buffer.readLine()) != null) {
builder.append(line);
}
buffer.close();
// Forward the response to mock service output
requestContext.responseMessage = builder.toString();

Invoke A Multipart REST Service with vaadin

I need to send a Multipart file data to REST service from vaadin . How can I achieve it ? .. ( web service API is listed below)
#RequestMapping(value="/upload", method=RequestMethod.POST)
public #ResponseBody String[] handleFileUpload(
#RequestParam( value="file" , required=false) MultipartFile file , #RequestParam( value="title" , required=false)String title ,#RequestParam( value="description" , required=false)String description ){
// file uploading logic....
}
When working with external HTTP based services in Java / VAADIN I'm ussualy using very nice JODD Java library specificaly http://jodd.org/doc/http.html
To post attachment to URL as explained in question, simply use something like this:
HttpRequest httpRequest = HttpRequest
.post("http://server:8080/upload")
.form(
"file", new File("c:\\a.jpg.zip")
);
HttpResponse httpResponse = httpRequest.send();
HttpRequest is object from JODD library. You can include JODD into maven config e.g. http://jodd.org/download/