Sending MultipartFile with some parameter to rest api in java - java

I am using rest api to send file with some data.
Below is the signature of API
#RequestMapping(value = "/file", method = RequestMethod.POST)
public ModelAndView uploadFile(HttpServletRequest request,
HttpServletResponse response,
#RequestParam(required = false) String wfid,
#RequestParam String ssoToken,
#RequestParam(required = false) String typeMedia,
#RequestParam(required = false) String synopsisParam,
#RequestParam(required = false) String slideShowParam,
#RequestParam(required = false) String embedInContentParam,
#RequestParam(required = false) boolean sizeRestrictionRequiredFlag,
#RequestParam MultipartFile file) throws Exception {
logger.info("SSO - " + ssoToken);
return "Output";
}
Below is my method in which i am creating POST request
void myMethod(String restAPI, String ssoId, byte[] imageByte){
PostMethod post = null;
HttpClient httpClient = new HttpClient();
try {
post = new PostMethod(restAPI);
Part[] parts = new Part[] { new FilePart("myImage.JPG", new ByteArrayPartSource("myImage.JPG", imageByte))};
HttpMethodParams par = post.getParams();
par.getDefaults().setParameter("ssoToken", ssoId);
MultipartRequestEntity multipartRequestEntity = new MultipartRequestEntity(parts, post.getParams());
ByteArrayOutputStream requestContent = new ByteArrayOutputStream();
multipartRequestEntity.writeRequest(requestContent);
post.setRequestEntity(multipartRequestEntity);
post.setRequestHeader("content-type", multipartRequestEntity.getContentType());
/*NameValuePair[] postParameters = new NameValuePair[]{new NameValuePair("ssoToken", ssoId)};
post.setRequestBody(postParameters);*/
int status = httpClient.executeMethod(post);
String responseBody = post.getResponseBodyAsString();
} catch(Exception e){
} finally{
if(post != null){
post.releaseConnection();
}
}
}
I am getting 400 - Required String parameter 'ssoToken' is not present
When i tried commented code
/NameValuePair[] postParameters = new NameValuePair[]{new NameValuePair("ssoToken", ssoId)};
post.setRequestBody(postParameters);/
in above method and send NameValue pair as response body above exception is resolve but Multipart file exception occur.
Can someone help how create request to rest controller mentioned above.
Kindly let me know the issue before down vote.
Thanks in advance

The reason this is not working, is because, the Name-Value in parameters do not isolate customer Request Parameters that your Rest api needs.
Essentially, java wouldn't know where to look into, to extract the RequestParam "ssoToken" that your rest controller expects.
What you can do, however is this -
Part[] parts = new Part[] { new FilePart("file",file), new StringPart("ssoToken",ssoToken) };
MultipartRequestEntity multipartRequestEntity = new MultipartRequestEntity(parts, par);
HttpMethodParams par = post.getParams();
Then proceed with the rest of the code as is.
The controller isolates the parts and searches for the "ssoToken" object, which it will now find!
This, I beleive should fix this problem!

Related

Trying to call/post a third party api in java spring

My issue is when I try this I get a media type error, then I changed the header. Now I receive a 500 error. The problem isnt the api , on postman it works perfectly , am I doing something wrong in my code when requesting a post?
My object model
public class EmailModel {
private String module;
private String notificationGroupType;
private String notificationGroupCode;
private String notificationType;
private String inLineRecipients;
private String eventCode;
private HashMap<String, Object> metaData;
public EmailModel() {
this.module = "CORE";
this.notificationGroupType = "PORTAL";
this.notificationGroupCode = "DEFAULT";
this.notificationType = "EMAIL";
this.inLineRecipients = "[chrispotjnr#gmail.com,chris#mqattach.com]";
this.eventCode = "DEFAULT";
this.metaData = metaData;
}
}
My Controller
It should send a post request with a object body, the emails get sent
#RequestMapping(value = "test", method = RequestMethod.Post)
public void post() throws Exception {
String uri = "TestUrl";
EmailModel em = new EmailModel();
EmailModel data = em;
HttpClient client = HttpClient.newBuilder().build();
HttpRequest request = HttpRequest.newBuilder()
.headers("Content-Type", "application/json")
.uri(URI.create(uri))
.POST(HttpRequest.BodyPublishers.ofString(String.valueOf(data)))
.build();
HttpResponse<?> response = client.send(request, HttpResponse.BodyHandlers.discarding());
System.out.println(em);
System.out.println(response.statusCode());
}
postmanImage
You must to convert EmailModel to json format by ObjectMapper
ObjectMapper objectMapper = new ObjectMapper();
String data = objectMapper
.writerWithDefaultPrettyPrinter()
.writeValueAsString(em);
and change POST to :
.POST(HttpRequest.BodyPublishers.ofString(data))
See more about ObjectMapper
Capture requests and cookies(on the left side of setting icon)
->Request
->port and put the port number there

I cannot send an HTTP request (500 internal server error)

I am currently receiving the following error for the http request am sending. I am trying to send a JSON Array list to trigger a method in the receiving end so as it saves the list in its database.
The 500 Internal Server Error is a very general HTTP status code that means something has gone wrong on the website's server, but the server could not be more specific on what the exact problem is.
Websites phrase 500 errors in many ways but they're all basically saying the same thing: there's a general server issue going on right now.
Most of the time there isn't anything you can do but contact the website directly and then wait on them to fix it.
In the off chance there is a problem on your end, try clearing the cache and deleting any cookies from the site with the error.
Please find the error below:
org.springframework.web.client.HttpServerErrorException: 500 Internal Server
public static String FRONT_URL;
public static String BACK_URL;
public static final String REST_SYNC = "rest/sync";
public static final String REST_API = "rest/api";
private Logger log = Logger.getLogger(FrontSynchronizer.class);
static final Logger synclog = Logger.getLogger("sync");
ResourceBundle rb = ResourceBundle.getBundle("bundles.sync-application-resources", Locale.getDefault());
//method sending the request
public void syncApplications(List<SchemeApplication> accList) {
schemeApplicationDto=new SchemeApplicationDto();
FRONT_URL = rb.getString("sync.front.url").concat(REST_SYNC);
BACK_URL = rb.getString("sync.back.url").concat(REST_API);
JSONArray array = new JSONArray();
if (accList != null && accList.size() > 0) {
for (SchemeApplication student : accList) {
schemeApplicationDto.setId(student.getId());
schemeApplicationDto.setAccountID(student.getAccountID());
schemeApplicationDto.setNoOfPersonsEmployedLocal(student.getNoOfPersonsEmployedLocal());
schemeApplicationDto.setLocalmainclients(student.getLocalmainclients());
JSONObject studentJSON = new JSONObject(schemeApplicationDto);
array.put(studentJSON);
}
}
HttpHeaders headers = new HttpHeaders();
JSONObject object = new JSONObject();
object.put("array", array);
headers.setContentType(MediaType.APPLICATION_JSON);
RestTemplate restTemplate = this.createnewTemplate();
String url = BACK_URL.concat("/application");
HttpEntity<String> requestEntity = new HttpEntity<String>(object.toString(), headers);
ResponseEntity<Boolean> responseEntity = restTemplate.exchange(url, HttpMethod.POST, requestEntity,
Boolean.class);
if (responseEntity.getBody())
{
for(SchemeApplication scheme:accList) {
schemeApplicationService.getDao().delete(scheme);
}
}
}
public RestTemplate createnewTemplate() {
// RestTemplate restTemplate = new RestTemplate(clientHttpRequestFactory());
HttpComponentsClientHttpRequestFactory httpRequestFactory = new HttpComponentsClientHttpRequestFactory();
httpRequestFactory.setConnectTimeout(120000);
RestTemplate restTemplate = new RestTemplate(httpRequestFactory);
return restTemplate;
}
// method that needs to process the request
//The method is trying to send an Array list so as the receiving end can receive the list and save it in its database.
#RequestMapping(value = "application", method = RequestMethod.POST)
public Boolean getAllArchivedpplications(#RequestBody String schemeJson) {
List<SchemeApplication> accList = null;
try {
accList = new ArrayList<SchemeApplication>();
if (StringUtils.isNotEmpty(schemeJson)) {
JSONObject listObject = new JSONObject(schemeJson);
JSONArray entryArray = listObject.getJSONArray("array");
for (int i = 0; i < entryArray.length(); i++) {
JSONObject res = new JSONObject(entryArray.get(i).toString());
ObjectMapper mapper = new ObjectMapper();
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
schemeApplication doc = mapper.readValue(res.toString(),
new TypeReference<schemeApplication>() {
});
accList.add(doc);
}
schemeService.getDao().save(accList); // Service.save accountlist;
}
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
#RequestBody must work on an object.
Standard way to do this kind of work in two ways:
Form a class having class files with same name and structure with your json data you are sending and capture that data in by #RequestBody annotation
As you are sending data as String, send it as request param, and use #RequestParam instead of #RequestBody and parse the way you need to do things. For I think for this kind of arrayList of bulk data you are working with, option 1 will be better/feasible.
For details you can check here: #RequestBody and #ResponseBody annotations in Spring

to avoid exception, disable SerializationFeature.FAIL_ON_EMPTY_BEANS)

I am trying to route HttpServletRequest to another microservice where request may contain multi-part request or any normal request. but while sending I am getting the below error.
Note: I dont want to modify the request as I am trying to write some generic method.
public Object doPostCall(HttpServletRequest request, String requestURL, String rootURL)
throws URISyntaxException, IOException, ServletException {
RestTemplate restTemplate = new RestTemplate();
final String url = rootURL + requestURL;
uri = new URI(url);
try {
result2 = restTemplate.postForEntity(uri, request, Object.class);
System.out.println("after service call" + result2);
} catch (RestClientException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return result2;
}
com.fasterxml.jackson.databind.exc.InvalidDefinitionException:
No serializer found for class java.util.Collections$3 and no properties discovered to create BeanSerializer (to avoid exception, disable SerializationFeature.FAIL_ON_EMPTY_BEANS) (through reference chain: org.springframework.web.multipart.support.StandardMultipartHttpServletRequest["request"]->org.springframework.session.web.http.SessionRepositoryFilter$SessionRepositoryRequestWrapper["request"]->org.apache.catalina.connector.RequestFacade["attributeNames"])
Even I have tried setting this in property file. spring.jackson.serialization.FAIL_ON_EMPTY_BEANS=false, but it didn't work
My Consume controller is like below:
#PostMapping(value = "/v1/upload/{moduleName}/{fileType}", produces = "application/json")
public ResponseEntity<Object> uploadFiles(#RequestPart("file") List<MultipartFile> inputFileList,
#RequestParam(value = "createdBy", required = false) String createdBy, #PathVariable String moduleName,
#RequestParam(value = "catalogId", required = false) String catalogId,
#RequestParam(value = "catalogName", required = false) String catalogName, #PathVariable String fileType) {
Try annotating your entity class with #JsonIgnoreProperties("hibernateLazyInitializer")

How to send multiple HTTP requests from the same service in Java?

Java noob here. I'm trying to develop a web service as per the following diagram.
When a POST request is sent to the REST server, with certain values, the values (being read from a list, in a loop) get inserted in a table (new row with an id). Server returns HTTP 202 Accepted.
To ensure that the resource(with id from 1) is created, a GET request is issued that returns the POJO as Json.
Finally a PATCH request is sent to update a certain column.
I have written a service class that does all three tasks when each API is called individually. I need to implement something that would automatically execute steps 2 and 3 when a POST request is sent to the server. Here's my code so far.
#Path("attachments")
public class FilesService {
private TiedostoService tiedostoService;
private AttachmentService attachmentService;
#GET
#Path("{id}")
#Produces({MediaType.APPLICATION_JSON})
public Response listAttachmentsAsJson(#PathParam("id") Integer attachmentId) throws Exception {
attachmentService = new AttachmentService();
Gson gson = new GsonBuilder().excludeFieldsWithoutExposeAnnotation().create();
Attachment attachment = attachmentService.getAttachment(attachmentId);
String jsonString = gson.toJson(attachment.toString());
return Response.status(Response.Status.OK).entity(jsonString).build();
}
#PATCH
#Path("{id}")
#Produces({MediaType.APPLICATION_JSON})
public Response patchAttachments(#PathParam("id") Integer attachmentId) throws Exception {
attachmentService = new AttachmentService();
Integer update = attachmentService.update(attachmentId);
String jsonString = new Gson().toJson(update);
return Response.status(Response.Status.ACCEPTED).entity(jsonString).build();
}
#POST
#Produces({MediaType.APPLICATION_JSON})
public Response migrateToMinio(#Context UriInfo uriInfo) throws Exception {
Response response;
List<String> responseList = new ArrayList<>();
tiedostoService = new TiedostoService();
attachmentService = new AttachmentService();
List<Tiedosto> tiedostoList = tiedostoService.getAllFiles();
String responseString = null;
int i = 1;
for (Tiedosto tiedosto : tiedostoList) {
Attachment attachment = new Attachment();
attachment.setCustomerId(tiedosto.getCustomerId());
attachment.setSize(tiedosto.getFileSize());
Integer id = attachmentService.createNew(attachment);
if (id == 1) {
UriBuilder builder = uriInfo.getAbsolutePathBuilder();
builder.path(Integer.toString(i));
response = Response.created(builder.build()).build();
System.out.println(response);
responseString = response.toString();
}
responseList.add(responseString);
i++;
}
String jsonString = new Gson().toJson(responseList);
return Response.status(Response.Status.OK).entity(jsonString).build();
}
}
when I test the individual endpoints with curl or postman, they work as expected, but I got stuck on how to execute GET and PATCH automatically after POST. I'd really appreciate some advice/suggestions/help.

Java PostMethod with xml

I am trying to post XML data as a body to a REST api.
I have a method that creates the request called doREST.
String url = null;
HttpMethod method;
LOG.info("QUERY: " + query);
if (StringUtil.isEmpty(query)) {
url = BuildRequestURL("/issues.ashx/issues/mywork");
method = doREST(url, false);
} else {
url = BuildRequestURL("/issues.ashx/issues/filters");
//method = doREST(url, true);
method = doREST(url, true);
String xml = "<IssuesFilterEN>" +
"<IssueID>" + query + "</IssueID>" +
"</IssuesFilterEN>";
RequestEntity entity = new StringRequestEntity(xml,"text/xml; charset=iso-8859-1", null);
method.setRequestEntity(entity);
}
and the doREST method
private HttpMethod doREST(String request, boolean post) throws Exception {
String uri = request;
HttpMethod method = post ? new PostMethod(uri) : new GetMethod(uri);
configureHttpMethod(method);
HttpClient client = getHttpClient();
client.getParams().setParameter(HttpClientParams.SO_TIMEOUT, timeoutLength);
client.executeMethod(method);
return method;
}
My issue is the method.setRequestEntity is saying that the method could not be found.
I have
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.HttpMethod;
import org.apache.commons.httpclient.methods.*;
If i set method = PostMethod instead of method = doREST it works but I don't want to have to do that in all my other methods just to create queries.
Is there something I am missing as to why the method.setRequestEntity is not working the way it is right now?
EDIT:
I got my information for using setRequestEntity from PostMethod setRequestBody(String) deprecated - why?
EDIT 2:
Here is what I ended up doing.
private HttpMethod doREST(String request, RequestEntity entity) throws Exception {
String uri = request;
HttpMethod method;
if ( entity != null ){
method = new PostMethod(uri);
((PostMethod) method).setRequestEntity(entity);
} else {
method = new GetMethod(uri);
}
configureHttpMethod(method);
HttpClient client = getHttpClient();
client.getParams().setParameter(HttpClientParams.SO_TIMEOUT, timeoutLength);
client.executeMethod(method);
return method;
}
You should modify doREST to accept the RequestEntity instead of a boolean. Pass in null for a GET and a value for POST. Use that as the check to see if you need a PostMethod or a GetMethod. Then you can have the specific type so you can call the PostMethod only setRequestEntity().
EDIT:
You can avoid the cast like this:
private HttpMethod doREST(String request, RequestEntity entity) throws Exception {
String uri = request;
HttpMethod method;
if ( entity != null ){
PostMethod postMethod = new PostMethod(uri);
postMethod.setRequestEntity(entity);
method = postMethod;
} else {
method = new GetMethod(uri);
}
configureHttpMethod(method);
HttpClient client = getHttpClient();
client.getParams().setParameter(HttpClientParams.SO_TIMEOUT, timeoutLength);
client.executeMethod(method);
return method;
}
The method you should be calling is setEntity, not setRequestEntity. Also, your body should be wrapped in a StringEntity, not a StringRequestEntity, imported from org.apache.http.entity.

Categories