I have a restcontroller with post method with following url and json request.
http://server/member/sc/v1/limited-liability/medicare
package com.dckr.microsvc.medicaredtls.controller;
import java.util.Map;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.StopWatch;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
#RestController
public class UpdMedicareDtlsController {
private static final Logger logger = LoggerFactory.getLogger(UpdMedicareDtlsController.class);
#Autowired
private UpdMedicareLLRecService updMedicareLLRecService;
#Autowired
ExceptionObjFactory expObjFactory;
#RequestMapping(value = UpdMedicareLLConstants.UPD_MEDICARE_LL_URL, method = RequestMethod.POST, consumes=MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE)
public InlineResponse200 updateMedicareLLRec(#RequestBody MedicareRequest updateMedicareRequest,
#RequestHeader(value=UpdMedicareLLConstants.META_TRANSID) String metatransid)
throws Exception {
long startTime = System.currentTimeMillis();
logger.info("Entering UpdMedicareDtlsController -- updateMedicareLLRec(#Request MedicareRequest updateMedicareReq)");
InlineResponse200 response = null;
StopWatch stopWatch = new StopWatch();
stopWatch.start();
logger.info( updateMedicareRequest.toString());
if(null!=updateMedicareRequest)
if ((null!=updateMedicareRequest.getMbruid()&&StringUtils.hasText(updateMedicareRequest.getMbruid()))
&&(null!=updateMedicareRequest.getMedicare()&&null!=updateMedicareRequest.getMedicare().getPrime()
&&StringUtils.hasText(updateMedicareRequest.getMedicare().getPrime()))
&&(null!=updateMedicareRequest.getMedicare()&&null!=updateMedicareRequest.getMedicare().getQualifiedReason()
&&StringUtils.hasText(updateMedicareRequest.getMedicare().getQualifiedReason()))
&&(null!=updateMedicareRequest.getLlSeqNum()&&StringUtils.hasText(updateMedicareRequest.getLlSeqNum()))
&&(null!=updateMedicareRequest.getMedicare()&&null!=updateMedicareRequest.getMedicare().getPartA()
&&null!=updateMedicareRequest.getMedicare().getPartA().getPrimary()
&&StringUtils.hasText(updateMedicareRequest.getMedicare().getPartA().getPrimary()))
&&(null!=updateMedicareRequest.getMedicare()&&null!=updateMedicareRequest.getMedicare().getPartB()
&&null!=updateMedicareRequest.getMedicare().getPartB().getPrimary()
&&StringUtils.hasText(updateMedicareRequest.getMedicare().getPartB().getPrimary()))) {
response = updMedicareLLRecService.updateLLRecord(updateMedicareRequest, metatransid);
} else {
throw expObjFactory.createNewAppexception("3002", UpdMedicareLLConstants.MISSING_MANDATORY_DATA);
}
else {
throw expObjFactory.createNewAppexception("3002", UpdMedicareLLConstants.MISSING_MANDATORY_DATA);
}
stopWatch.stop();
logger.info("Exiting UpdMedicareDtlsController -- updateMedicareLLRec() time taken : "+ stopWatch.getTotalTimeMillis());
return response;
}
}
While triggering the request in local with post method and json request, getting proper response. but running as spring boot app in docker is throwing exception as method not allowed. Initially i deployed this docker service as put method. now i have moved to post method. If i change my method back to put method. this is working fine.
response:
Date Mon, 04 Jun 2018 09:30:16 GMT
Content-Length 0
status# HTTP/1.1 405 Method Not Allowed
Allow POST
Connection keep-alive
X-Application-Context scupdatemedicaredtls:sit
Server nginx/1.13.10
Anybody please suggest appropriate response.
Your runtime jar isn't deployed with a post method corresponding with your path and parameters. Double check your deployment.
Related
import com.google.gson.Gson;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.data.jpa.mapping.JpaMetamodelMappingContext;
import org.springframework.http.MediaType;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.ResultActions;
import preproject.underdog.answer.dto.answer.AnswerPostDto;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
#WebMvcTest(value = AnswerController.class)
//#AutoConfigureRestDocs
#MockBean(JpaMetamodelMappingContext.class)
public class AnswerController {
#Autowired
private MockMvc mockMvc;
#Autowired
private Gson gson;
#Test
#DisplayName("답변 글 작성 테스트")
void postAnswer() throws Exception {
AnswerPostDto post = new AnswerPostDto("테스트", 1L, 1L);
String content = gson.toJson(post);
ResultActions actions =
mockMvc.perform(
post("/answers")
.accept(MediaType.APPLICATION_JSON)
.contentType(MediaType.APPLICATION_JSON)
.content(content)
);
actions
.andExpect(status().isCreated());
}
import lombok.RequiredArgsConstructor;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import preproject.underdog.answer.dto.answer.AnswerPostDto;
import preproject.underdog.answer.dto.answer.AnswerRespDto;
import preproject.underdog.answer.mapper.AnswerMapper;
import preproject.underdog.answer.service.AnswerService;
import javax.validation.Valid;
import java.time.LocalDateTime;
#RestController
#RequestMapping("/answers")
#Validated
#RequiredArgsConstructor
public class AnswerController {
private final AnswerService answerService;
private final AnswerMapper answerMapper;
#PostMapping
public ResponseEntity postAnswer(#Valid #RequestBody AnswerPostDto answerPostDto) {
AnswerRespDto answerRespDto = new AnswerRespDto(1L,"테스트",1L,1L,1L, LocalDateTime.of(2023, 4, 3, 3, 3, 0),LocalDateTime.of(2023, 4, 3, 3, 3, 0));
return new ResponseEntity<>(answerRespDto, HttpStatus.CREATED);
}
Here's my codes first,
I tried make Rest Docs first, but I faced a lot of errors, so I just started to try pass the MockMVC test first.
So I gotta got 201 response from that, but I only got 404 error
here's my log.
MockHttpServletRequest:
HTTP Method = POST
Request URI = /answers
Parameters = {}
Headers = [Content-Type:"application/json;charset=UTF-8", Accept:"application/json", Content-Length:"49"]
Body = {"content":"테스트","userId":1,"questionId":1}
Session Attrs = {}
Handler:
Type = org.springframework.web.servlet.resource.ResourceHttpRequestHandler
Async:
Async started = false
Async result = null
Resolved Exception:
Type = null
ModelAndView:
View name = null
View = null
Model = null
FlashMap:
Attributes = null
MockHttpServletResponse:
Status = 404
Error message = null
Headers = [Vary:"Origin", "Access-Control-Request-Method", "Access-Control-Request-Headers"]
Content type = null
Body =
Forwarded URL = null
Redirected URL = null
Cookies = []
#PostMapping
public ResponseEntity postAnswer(#Valid #RequestBody AnswerPostDto answerPostDto) {
return new ResponseEntity<>(HttpStatus.CREATED);
}
I even tried to changed the code to get only 201 response like this
but it still gave me 404 error
What should I do?? thanks
I want to response my Json Object after my Post request but when i do this i've got an internal server HTTP 500.
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import com.example.demo.beans.*;
import com.google.gson.JsonObject;
import programm.Manager;
#Controller
public class StudentRegistrationController {
#ResponseBody
#RequestMapping(method = RequestMethod.POST)
public StudentRegistrationReply registerStudent(#RequestBody Student student) {
JsonObject t;
StudentRegistrationReply stdregreply = new StudentRegistrationReply();
StudentRegistration.getInstance().add(student);
//Manager m = new Manager();
t = Manager.solvingProcess(student.getContext(), student.getFilename());
stdregreply.setSolution(t);
return stdregreply;
}
}
Call the Method at Manager is no problem it do everything what it should. But at Postman e.g., I got a HTTP 500 and I don't understand why.
{
"timestamp": "2020-09-10T06:28:21.159+00:00",
"status": 500,
"error": "Internal Server Error",
"message": "",
"path": "/"
}
Has anyone an idea? My Manager class only format an String into JSONObject with JSONArray inside, there works everything fine.
I solved the Problem. The problem was i use JSON from google.gson and the httpresponse can't use it. I changed the JSON to Json from simple.json and everything works fine.
Edit:
I tried to implement the suggestions of #Durgpal Singh and #Nikhil. I changed the code so it looks like this.
Client:
Client client = ClientBuilder.newClient();
WebTarget target = client
.target("http://localhost:8087/api/ls3algorithm/" + petrinets + "/" + Integer.toString(k) + "/" + Float.toString(theta));
Invocation.Builder invocationBuilder = target.request(MediaType.APPLICATION_JSON);
Response response = invocationBuilder.get();
Map<String, List<Map>> result_ = response.readEntity(new GenericType<Map<String, List<Map>>>() { });
result = (ArrayList<Map>) result_.get("data");
Server:
ArrayList<Map> result;
result = new Ls3Algorithm().execute(new File("petrinetze").getAbsolutePath(), k, theta);
Map<String, List<Map>> map = new HashMap<>();
map.put("data", result);
return Response.ok(map).build();
Unfortunately this leads to Exception in thread "main" org.glassfish.jersey.message.internal.MessageBodyProviderNotFoundException: MessageBodyReader not found for media type=application/json, type=interface java.util.Map, genericType=java.util.Map<java.lang.String, java.util.List<java.util.Map>>.
Where do I go wrong?
-------------------------------
I'm pretty new to RESTful web services and currently writing a microservice which provides a calculating algorithm. I'm testing the service as posted below.
Workflow:
Client saves some data in a MongoDB database and sends the names of the relevant files via #PathParam as part of the GET request. The server then retrieves the files from the MongoDB, processes its algorithm and sends back the result as List<Map> packed in a Response object.
Goal:
Transfer the result (List<Map>) as JSON and print it out on the client console.
Client:
package ls3test;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Map;
import javax.ws.rs.client.Client;
import javax.ws.rs.client.ClientBuilder;
import javax.ws.rs.client.Invocation;
import javax.ws.rs.client.WebTarget;
import javax.ws.rs.core.GenericType;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.ObjectWriter;
import com.mongodb.DB;
import com.mongodb.MongoClient;
import com.mongodb.gridfs.GridFS;
import com.mongodb.gridfs.GridFSInputFile;
public class Ls3TransmissionTest {
final static String petrinets = "eins, zwei, drei, vier";
final static int k = 3;
final static float theta = 0.9f;
public static void main(String[] args) throws IOException {
[... save all the relevant files in the MongoDB ...]
ArrayList<Map> result = new ArrayList<Map>();
Client client = ClientBuilder.newClient();
WebTarget target = client
.target("http://localhost:8087/api/ls3algorithm/" + petrinets + "/" + Integer.toString(k) + "/" + Float.toString(theta));
Invocation.Builder invocationBuilder = target.request(MediaType.APPLICATION_JSON);
Response response = invocationBuilder.get();
result = response.readEntity(new GenericType<ArrayList<Map>>() {
});
ObjectWriter ow = new ObjectMapper().writer().withDefaultPrettyPrinter();
String json = ow.writeValueAsString(result);
}
}
Server:
package service;
import com.fasterxml.jackson.core.JsonGenerationException;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.mongodb.DB;
import com.mongodb.MongoClient;
import com.mongodb.gridfs.GridFS;
import com.mongodb.gridfs.GridFSDBFile;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.GenericEntity;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Files;
import java.util.List;
import java.util.Map;
#SuppressWarnings("deprecation")
#Path("/ls3algorithm")
public class Resource {
// SLF4J is provided with Dropwizard
Logger log = LoggerFactory.getLogger(Resource.class);
#SuppressWarnings("rawtypes")
#GET
#Path("/{petrinets}/{k}/{theta}")
#Produces(MediaType.APPLICATION_JSON)
public Response ls3execute(#PathParam("petrinets") String petrinetNames, #PathParam("k") int k,
#PathParam("theta") float theta) {
[... get all the relevant files from the MongoDB ...]
List<Map> result;
Ls3Algorithm ls3Algorithm = new Ls3Algorithm();
result = ls3Algorithm.execute(new File("petrinetze").getAbsolutePath(), k, theta);
GenericEntity<List<Map>> entity = new GenericEntity<List<Map>>(result) {};
Response response = Response.ok(entity).build();
return response;
}
}
This is not working, the exception I get is posted below:
Exception in thread "main" org.glassfish.jersey.message.internal.MessageBodyProviderNotFoundException: MessageBodyReader not found for media type=application/json, type=class java.util.ArrayList, genericType=java.util.ArrayList<java.util.Map>.
at org.glassfish.jersey.message.internal.ReaderInterceptorExecutor$TerminalReaderInterceptor.aroundReadFrom(ReaderInterceptorExecutor.java:231)
at org.glassfish.jersey.message.internal.ReaderInterceptorExecutor.proceed(ReaderInterceptorExecutor.java:155)
at org.glassfish.jersey.message.internal.MessageBodyFactory.readFrom(MessageBodyFactory.java:1085)
at org.glassfish.jersey.message.internal.InboundMessageContext.readEntity(InboundMessageContext.java:874)
at org.glassfish.jersey.message.internal.InboundMessageContext.readEntity(InboundMessageContext.java:834)
at org.glassfish.jersey.client.ClientResponse.readEntity(ClientResponse.java:368)
at org.glassfish.jersey.client.InboundJaxrsResponse$2.call(InboundJaxrsResponse.java:126)
at org.glassfish.jersey.internal.Errors.process(Errors.java:315)
at org.glassfish.jersey.internal.Errors.process(Errors.java:297)
at org.glassfish.jersey.internal.Errors.process(Errors.java:228)
at org.glassfish.jersey.process.internal.RequestScope.runInScope(RequestScope.java:419)
at org.glassfish.jersey.client.InboundJaxrsResponse.runInScopeIfPossible(InboundJaxrsResponse.java:267)
at org.glassfish.jersey.client.InboundJaxrsResponse.readEntity(InboundJaxrsResponse.java:123)
at ls3test.Ls3TransmissionTest.main(Ls3TransmissionTest.java:89)
Ls3TransmissionTest.java:89 is ObjectWriter ow = new ObjectMapper().writer().withDefaultPrettyPrinter();
I spent plenty of time now doing research on this problem, but I cannot find an example that really fits it. What do I miss? Any help or hint is highly appreciated!
You can send a map. Like this
Map<String, Object> map = new HashMap<>();
map.put("data", entity);
Response.ok(map).build();
return Response;
Cannot see why do you need to wrap the List with GenericEntity. Something as simple as below will work:-
#SuppressWarnings("rawtypes")
#GET
#Path("/{petrinets}/{k}/{theta}")
#Produces(MediaType.APPLICATION_JSON)
public Response ls3execute(#PathParam("petrinets") String petrinetNames, #PathParam("k") int k,
#PathParam("theta") float theta) {
//[... get all the relevant files from the MongoDB ...]
List<Map> result;
Ls3Algorithm ls3Algorithm = new Ls3Algorithm();
result = ls3Algorithm.execute(new File("petrinetze").getAbsolutePath(), k, theta);
Response response = Response.ok(result).build();
return response;
}
And in the client side,
String result = response.readEntity(String.class);
return result;
I was trying postman with a Java clientava client. I was getting the following output
com.squareup.okhttp.internal.http.RealResponseBody#c9673cf
the original output is
Curl -I "http://ec2-52-34-14-38.us-west-2.compute.amazonaws.com:14000/webhdfs/v1/user/ec2-user/prediction_output/part-00000?user.name=ec2-user&op=OPEN"
1234.566788
here is my java code.
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.Response;
import com.squareup.okhttp.OkHttpClient;
import com.squareup.okhttp.Request;
import java.io.IOException;
#Path("/hello")
public class HelloWorldService {
#GET
#Produces("application/json")
public Response getMsg() throws IOException {
OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder()
.url("http://ec2-52-34-14-38.us-west-2.compute.amazonaws.com:14000/webhdfs/v1/user/ec2-user/prediction_output/part-00000?user.name=ec2-user&op=OPEN")
.build();
com.squareup.okhttp.Response responses = null;
responses = client.newCall(request).execute();
System.out.println(responses);
return Response.status(200).entity(responses.body().toString()).build();
}
}
any help will be appreciated.
Use response.body().string() not toString().
Use the above also in System.out.println.
Your method getMsg() says #Produces("application/json") but your built response is text/plain.
I want to build a RestAPI and return a JSONObject as response.
Therefore I created this controller:
import java.util.List;
import org.json.JSONArray;
import org.json.JSONObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
#RestController
#RequestMapping("/api")
public class ApiController {
#Autowired
private AssemblyRepository assemblyRepo;
#RequestMapping(method=RequestMethod.POST)
public ResponseEntity<JSONObject> sendResponse(#RequestBody AppRequest request) {
//do some stuff with the data from requestBody
List<Assembly> assemblys = assemblyRepo.findAll();
JSONArray t_sub_objlist = new JSONArray();
for (Assembly a: assemblys) {
JSONObject object = new JSONObject();
object.put("obj_type", a.getObjType());
object.put("obj_key", a.getObjKey());
t_sub_objlist.put(object);
}
response.put("t_sub_objlist", t_sub_objlist);
return new ResponseEntity<JSONObject>(response, HttpStatus.OK);
}
}
When I print the response to the console everything looks good: {"t_sub_objlist":[{"obj_key":"MS","obj_type":"NT"},{"obj_key":"MV","obj_type":"NT"}]}
But when I want to access the API from outside, the first time after restarting the server, I get this error message:
There was an unexpected error (type=Not Acceptable, status=406).
Could not find acceptable representation
And if i try again then this message always comes up:
There was an unexpected error (type=Internal Server Error, status=500).
Could not write content: No serializer found for class org.json.JSONObject and no properties discovered to create BeanSerializer (to avoid exception, disable SerializationFeature.FAIL_ON_EMPTY_BEANS) ); nested exception is com.fasterxml.jackson.databind.JsonMappingException
I don't know what I'm doing wrong here :)