Wanted to test a post request in POSTMAN.
public enum TimeUnit {
HOURS("hours"),
MINUTE("mins");
private String value;
public static TimeUnit get(String text) {
return Arrays.stream(TimeUnit.values())
.filter(a -> Objects.equals(a.getValue(), text))
.findFirst()
.orElse(null);
}
}
public final class SchoolTimeTable {
private Double value;
private TimeUnit unit;
public SchoolTimeTable (double value, TimeUnit unit) {
this.value = value;
this.unit=unit;
}
}
public class SchoolDto {
private String name;
private String address;
private MultipartFile profileImage;
private MultipartFile[] galleryImages;
private SchoolTimeTable openCloseTime;
}
Spring MVC Controller
#PostMapping(value = "/schoolInfo", produces = { MediaType.APPLICATION_JSON_VALUE })
public ResponseEntity<Object> saveSchoolInfo( #Parameter(required = true, schema = #Schema(implementation = SchoolDto.class)) SchoolDto schoolDto) throws IOException, InterruptedException {
...
}
I want to send SchoolDto (POSTMAN: body->raw->json) in post request to get desired result. But I am not able to create the json which supports SchoolTimeTable (Object) and MultipartFile types. I don't even know whether it is possible with JSON or not.
Note: Same could be achieved using body->form-data with key/value.
Please help.
I think you should not upload files within a application/json request, to do so you should use a multipart/form-data request. Your request may have three parts profileImage, galleryImages and schoolInfo.
Remove profileImage and galleryImages from SchoolDto class
Modify your method signature to support the multipart request
#PostMapping(value = "/schoolInfo", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
public ResponseEntity<Object> saveSchoolInfo(#RequestPart(value = "profileImage") MultipartFile profileImage, #RequestPart(value = "galleryImages") MultipartFile[] galleryImages, #RequestPart(value = "schoolInfo") SchoolDto schoolInfo) throws IOException, InterruptedException {
...
}
In addtion you can implement a #SpringBootTest unit test using RestDocumentationExtension to check whether your code works and to produce a curl request sample that will help you to understand how to make a request to your endpoint
See sb-mvc-multipart-demo
When I have used multipart/form-data I was using Spring Boot 2.0.x, Java 8 and with the same method = POST
There are points that you need to implement correctly. Maybe this can help you:
#RequestMapping(value = MEUVOUCHER_FILE, method = POST, consumes = "multipart/form-data", produces = APPLICATION_JSON_UTF8_VALUE)
#ResponseStatus(code = CREATED)
public ObjectResponse<MEUVOUCHERFileRetrievalDto> createMEUVOUCHERFile(
#RequestPart("MEUVOUCHERFile") MultipartFile MEUVOUCHERFile,
#ApiParam(name = "metadata", value = "{ \"MEUVOUCHERTypeId\" : 0, \"relatedContentId\" : 0, \"expireDate\" : \"datetime\" }", required = true)
this may or may not be a somewhat long post, but I'm going to be pasting every single piece of information relating to this issue and the method I am testing, from Controller class with method to the a.jax snippet. I have asked about 4-6 developers and no one can find out the reason why its giving me a 415 error instead of a 200, because it just seems like I am doing everything correct. I just need some fresh eyes and new perspectives, hopefully someone could help me solve this. I will be pasting the classes and the relevant pieces now, and then a couple comments after the snippets.
Controller class
#Controller
#RequestMapping(value = "/user")
public class Controller
{
#Autowired
private Service service;
public Controller() {
}
#RequestMapping(value = "/landing/{age}/{name}/{title}/{family}/{gender}", method = RequestMethod.PUT, consumes = MediaType.APPLICATION_JSON, produces = MediaType.APPLICATION_JSON)
public #ResponseBody String update(#RequestBody HouseModel model, #PathVariable int age, #PathVariable String name, #PathVariable String title, #PathVariable String family, #PathVariable String gender)
{
String result = service.update(model, age, name, title, family, gender);
// this will just return the string "Success" if update works or "Failed" if query is
wrong or not found
return result;
}
Service Class
#Service
public class Service
{
#Autowired
Dao dao;
public Service() {
}
public String update(HouseModel model, int age, String name, String title, String family)
{
return dao.update(HouseModel model, int age, String name, String title, String family);
}
}
Dao class
#Repository
public class Dao
{
public Dao () {
}
public String update(HouseModel model, int age, String name, String title, String family)
{
String result = "";
//some long query that updates the table and will populate result as "Success" or "Failed"
return result
}
}
Controller test class
#EnableWebMvc
#WebAppConfiguration
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(locations = { "classpath:applicationContext-testing.xml",
"classpath:applicationContext-EIPW.xml"})
public class ControllerTest {
#Autowired
private Controller controller;
#Autowired
private WebApplicationContext webApplicationContext;
private MockMvc mockMvc;
#Before
public void setup() throws Exception {
this.mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext).build();
}
#Test
public void test_update() throws Exception {
String URI = "/user/landing/22/Test/Mr/Yes/Male";
String content = "{\n \"HouseId\": 5,\n \"DateOfPurchase\": \"2019-01-01\",\n \"Price\": 100,\n \"Floors\": 5,\n \"Style\": \"Victorian\",\n}";
MockHttpServletRequestBuilder requestBuilder = MockMvcRequestBuilders.put(URI).contentType(MediaType.APPLICATION_JSON).content(content).accept(MediaType.APPLICATION_JSON);
MvcResult mvcResult = mockMvc.perform(requestBuilder).andDo(MockMvcResultHandlers.print()).andReturn();
}
j.ajax
$j.ajax({
headers: {
Accept: "application/json",
"Content-Type": "application/json"
},
type: "PUT",
async: false,
data: JSON.stringify(
buildEdit(editRecords[i], ecRecord)
),
url:
"/user/landing/22/Test/Mr/Yes/Male",
dataType: "text"
printed error message
MockHttpServletRequest:
HTTP Method = PUT
Request URI = /user/landing/22/Test/Mr/Yes/Male
Parameters = {}
Headers = {Content-Type=[application/json], Accept=[application/json]}
Handler:
Type = controller.Controller
Async:
Was async started = false
Async result = null
Resolved Exception:
Type = org.springframework.web.HttpMediaTypeNotSupportedException
ModelAndView:
View name = null
View = null
Model = null
FlashMap:
MockHttpServletResponse:
Status = 415
Error message = null
Headers = {Accept=[application/octet-stream, */*, text/plain;charset=ISO-8859-1, */*, application/xml, text/xml, application/*+xml, application/x-www-form-urlencoded, multipart/form-data]}
Content type = null
Body =
Forwarded URL = null
Redirected URL = null
Cookies = []
Some Comments:
So I've had over 50 stack overflow tabs open relating to the same problem, and a lot of them had similar solutions that seemed so simple. Here are some, if not all of the things I did in attempts to try and solve this problem:
Switched around the content-type and accepts headers of requestBuilder to be MediaTypes of APPLICATION_JSON or APPLICATION_JSON_VALUE or ALL_VALUE, etc
Added produces or consumes = "application/json" or MediaType.APPLICATION_JSON/APPLICATION_JSON_VALUE/ALL_VALUE into the requestMapping().
Played around with a.jax to change content-type or accepts around
A couple of other things that I don't remember, but alas the 415 status is still here
I also do have setters and a default constructor in the HouseModel, and default constructors in every layer. I am 99.9% sure I have tried almost everything, if not everything, unless I am just missing something and am being stupid then yeah. I sent the request with the body as JSON raw an as:
{
"HouseId": 5,
"DateOfPurchase": "2019-01-01",
"Price": 100,
"Floors": 5,
"Style": "Victorian",
}
and it returned back success, I will attach its headers here:
[![Picture Link][1]][1]
[1]: https://i.stack.imgur.com/AqKnY.png
There is something interesting though, I did get one method to work but it required no arguments in its parameters, it was just a get method (dao calls database to store stuff in a list):
**Controller method**
#RequestMapping(value = "/levels", method = RequestMethod.POST, produces = "application/json")
public #ResponseBody String getLevels() throws Exception
{
ObjectMapper mapper = new ObjectMapper();
// there is a long logic after this map to populate the map
Map<LevelObject, List<LevelObject>> map = new HashMap<LevelObject, List<LevelObject>>();
return mapper.writeValueAsString(map);
}
This is such a simple test and it worked perfectly fine, giving me a status 200 and my expected result.
**Test class method**
#Test
public void test_getLevels() throws Exception {
String URI = "/user/levels";
MockHttpServletRequestBuilder requestBuilder = MockMvcRequestBuilders.post(URI).accept(MediaType.APPLICATION_JSON);
MvcResult mvcResult = mockMvc.perform(requestBuilder).andExpect(status().isOk()).andReturn();
}
**j.ajax for the getLevels method**
$j.ajax({
type: "POST",
url: "user/levels",
async: false,
dataType: "json",
Thank you so much!
Though I am not a front-end developer, I am sure that problem is in below line
data: JSON.stringify(
buildEdit(editRecords[i], ecRecord)
)
Reason - I tested your code locally. Code works fine from postman, if I select request body as raw and type as JSON
But if select request body as raw and type as "TXT". I am getting same error as you.
[![enter image description here][2]][2]
So, I am sure that your request body is not being built as JSON. rather it is being sent as some other format. Hence, the error.
[2]: https://i.stack.imgur.com/cqSCC.png
Also, you can try to change dataType: "text" to dataType: "json"
Please try the below,
$j.ajax({
headers: {
Accept: "application/json",
"Content-Type": "application/json"
},
type: "PUT",
async: false,
data:
buildEdit(editRecords[i], ecRecord),
url:
"/user/landing/22/Test/Mr/Yes/Male",
dataType: "json"
Remove converting the json to String
Change the dataType to json
I am writing a Spring Boot application. My controller has 2 custom request headers. I was executing a couple of tests only to find out that my application returns a '404' when the headers are not present.
I however was expecting this to lead to a '400' error?
Can anyone elaborate why this is happening? And how I should handle it properly? As in tell the consumer of the service the headers are missing?
#RestController("fundsConfirmationController")
#RequestMapping(
value="/accounts/{accountId}/funds-confirmations",
headers = {"X-CAF-MSGID", "X-AccessToken"}
)
public class FundsConfirmationController implements FundsConfirmationControllerI{
private FundsConfirmationServiceI fundsConfirmationService;
#Autowired
public FundsConfirmationController(FundsConfirmationServiceI fundsConfirmationService){
this.fundsConfirmationService = fundsConfirmationService;
}
#GetMapping(
consumes = MediaType.APPLICATION_JSON_VALUE,
produces = MediaType.APPLICATION_JSON_VALUE
)
public ResponseEntity<?> fundsConfirmation(#RequestHeader(value="X-CAF-MSGID") String messageId,
#RequestHeader(value="X-AccessToken") String accessToken,
FundsConfirmationRequest requestParams) { ... }
2 solutions to do the same.
First using #RequestHeader with required false
#RequestMapping(value = "/{blabla}", method = RequestMethod.POST)
public void post(#RequestHeader(value="X-CAF-MSGID", required=false) String X-CAF-MSGID) {
if(X-CAF-MSGID == null) {
// Your JSON Error Handling
} else {
// Your Processing
}
}
Second using HttpServletRequest instead of #RequestHeader
#RequestMapping(value = "/{blabla}", method = RequestMethod.POST)
public void post(HttpServletRequest request) {
String X-CAF-MSGID = request.getHeader("X-CAF-MSGID");
if(X-CAF-MSGID == null) {
// Your JSON Error Handling
} else {
// Your Processing
}
}
I'm working on a java spring mvc application. I need to send an xml string to my controller, and get this xml as a simple text string inside controller. But can not find any solution yet. I tried this way:
#RequestMapping(value = "/test", method = RequestMethod.POST)
public String test(String post, HttpServletRequest request, HttpServletResponse response){
System.out.println("post: " + post);
}
and I have contentType: 'text/xml' in my ajax config. But the variable post always printed as null.
Also I tried consumes = MediaType.APPLICATION_XML_VALUE and consumes = MediaType.TEXT_XML_VALUE in my method, but returns me HTTP Status 415 – Unsupported Media Type. What is the problem? How can I send simple xml text to my controller?
You can read your string using RequestParam:
#RequestMapping(value = "/test", method = RequestMethod.POST)
public String test(
#RequestParam(value="post") String post, Model model){
...
}
This is a REST application using Spring Framework.
Look, in some point of the payment process, I request the form to redirect to the payment URL:
#RequestMapping( value="/{id}/online-payment", produces="text/html", method={ RequestMethod.POST, RequestMethod.GET } )
#ResponseBody
public String onlinePaymentForm( HttpServletResponse response,
#PathVariable( value="id" )String eventId,
#RequestParam( value="temporalDataId", required=true )String temporalDataId,
#RequestParam( value="amount", required=true )Double amount
) throws Exception
{
...
else if( conn.getGateway() == PaymentGateway.PAYPAL)
{
return paypalPaymentsServices.buildPaymentForm(
conn, temporalDataId, amount, event.getName(), data.representantParticipant() );
}
...
}
When the application gets the form, auto submit the obtained form (onload=submitForm()). What I want to do is to put the current URL or the current domain name in the response form, for example:
I know how to do it using HttpServletRequest request with request.getRequestURL(), but as you can see this method is receiving an HttpServletResponse response.
Maybe exists is a class with static methods or a way to get the current URL using Spring Framework or Java?
Thanks.
If you add a request parameter, then you should be able to use it; e.g.
#RequestMapping(value="/{id}/online-payment", produces="text/html",
method={RequestMethod.POST, RequestMethod.GET})
#ResponseBody
public String onlinePaymentForm(
HttpServletResponse response,
HttpServletRequest request,
#PathVariable(value="id") String eventId,
#RequestParam(value="temporalDataId", required=true) String id,
#RequestParam(value="amount", required=true) Double amount
) {
...
}
The mapping infrastructure recognizes and binds a HttpServletRequest parameter if you are within a Servlet based container.