I have two services running. One service will generate a JSON response. Below is the generated Json response.
{ "appliedCostMatrix": { "regionCostMatrix": "","costAreaCode": "", "costBoundaryId": 0, "isActive": "Y", "costRegionCode": "", "regionTypeCode": 3, "regionTypeDescription": "California", "solveTypeDescription": "Coaxial" }, "networkSolveRegion": "CALIFORNIA"}
Now To save the response i have to call other service and have to pass this Json as string.
http://localhost:8080/putSolvedRoutes?responseJson=(Above Mentioned JSON string)
Can any one tell me the best way to achieve this.
Thanks in Advance.
What have you tried? Your tags imply this is a Spring question so within the context of Spring boot, set up your controller (that receives the second request you send with the json data) as follows:
#RestController
public class YourRestController {
#RequestMapping(value="/your/endpoint", method=RequestMethod.POST)
public ResponseEntity<String> someMethod(#RequestBody YourDTO data) {
// business logic here
}
}
and send the request with whatever client you are using, in post.
If the client is also Spring, have a look at the documentation for one possible way to solve the problem. A brief example:
#Service
public class YourService {
private final RestTemplate rt;
public YourService(RestTemplateBuilder rtb) {
this.rt = rtb.build();
}
public YourDTO someRestCall(String param) {
return this.rt.postForObject("/your/endpoint", YourDTO.class, param);
}
}
Related
I am new to Java and Spring boot. I am creating a new API.
Using postman I am sending a request body which contains request header and request payload.
Then I have a controller which handles the request with the help of RequestPayload class. (And a service and dao file but I am sure those are ok.)
Kindly let me know what Am I missing here or what do I not know.
public class RequestPayload {
String pol_pkg_prod_code;
JSONObject checklist;
public JSONObject getCheckList() {
return checklist;
}
public void setCheckList(JSONObject checklist) {
this.checklist = checklist;
}
public String pol_pkg_prod_code() {
return pol_pkg_prod_code;
}
public void setpol_pkg_prod_code(String pol_pkg_prod_code) {
this.pol_pkg_prod_code = pol_pkg_prod_code;
}
You need a POJO class that will match the structure of your JSON payload, actually a few nested classes. Spring will automatically parse JSON into this POJO.
public class Request {
private RequestPayload reqPayload;
// Getter Setter
}
public class RequestPayload {
private Checklist checklist;
// Getter Setter
}
public class Checklist {
#JsonProperty("pol_pkg_prod_code")
private String polPkgProdCode;
}
Then add it to Controller as an argument like this:
#RequestBody Request request
This tutorial explains it well
https://www.baeldung.com/spring-request-response-body
I using postman and spring boot. In spring boot i using code look like :
public PersistableCategory createCategory(#RequestBody PersistableCategory persistableCategory, MerchantStore store, HttpServletRequest httpRequest) {
MerchantStore merchantStore = (MerchantStore) httpRequest.getAttribute("MERCHANT_STORE");
return categoryService.saveCategories(store,persistableCategory);
}
get attribute from httpservletrequest. But i can't know where i set attribute with name MERCHANT_STORE in postman. I set in body look like
{
"attributes": {
"MERCHANT_STORE": {
"code":"1"
}
},
but it not working. How to set attribute in postman and using HttpServletRequest get it.
if you have more APIs, and need to response like the request (more than one depth attribute)
{
"attributes": {
"MERCHANT_STORE": {
"code":"1",
"code2":{
"element1":"1",
"element2":"2"
}}}
2.First, make a class for response.
public class responseData {
private merchant_store;
// getter, setter, the other elements..
}
i think that's better to make to make class for setting results.
public class result{
private View json; // this object from spring servlet lib.
// and make methods to parse http header(yep, in postman) and to return datas.
}
Let's make response in controller.
public PersistableCategory createCategory(){
MerchantStore merchantStore = (MerchantStore);
httpRequest.getAttribute("MERCHANT_STORE");
Object purpose = categoryService.saveCategories(store,persistableCategory);
Object responseData = new responseData();
responseData.set(purpose);
result.set(responseData, successYn);
return result;
}
Well, successYn is just String in my
Because i wanted to know whether it finished to access DB and set Datas.
if you want you can set other types.
Using Spring Boot I've build a toy REST service with a single resource like so:
#RestController
#RequestMapping("/checkout")
public class CheckoutRestController {
#PostMapping("/book")
public boolean buyBook(#RequestParam CreditCard creditCard, #RequestParam ShippingAddress shippingAddress) {
return true;
}
}
Both CreditCard and ShippingAddress are POJOs (plain old Java objects) that I've coded up).
I've tried posting to this endpoint with this payload:
{
"creditCard" : {
"nameOnCard":"foo",
"number":12345678,
"expiryMonth":12,
"expiryYear":2018,
"ccv":100
},
"shippingAddress" : {
"steert":"foor",
"houseNumber":"1a",
"city":"bar",
"state":"bazz",
"country":"buzz",
"zipCode":"booz"
},
}
But I get an error:
{
"timestamp": "2018-03-13T11:36:52.745+0000",
"status": 400,
"error": "Bad Request",
"message": "Required CreditCard parameter 'creditCard' is not present",
"path": "/checkout/book"
}
I know a workaround would be to wrap both POJOs in a request wrapper but I'd rather not unless I really have to.
Is it possible to post two #RequestParam annotated objects? If so, what would the JSON look like?
#RequestParam parameters are query parameters, not body parameters.
This means that your method:
#PostMapping("/book")
public boolean buyBook(#RequestParam CreditCard creditCard, #RequestParam
ShippingAddress shippingAddress) {
return true;
}
Expects the following request:
POST /checkout/book?creditCard=<...>&shippingAddress=<...>
However, Spring doesn't know how to convert a String query parameter to CreditCard or to ShippingAddress.
You might solve this by implementing a Converter, as follows:
public class StringToCreditCardConverter implements Converter<String, CreditCard> {
#Override
public CreditCard convert(String source) {
<...>
}
}
However, I do not recommend this as it is not the standard for request bodies and would cause quite a lot of confusion and maintainability issues.
Instead, the recommended way is as follows:
#PostMapping("/book")
public boolean buyBook(#RequestBody BookCreationRequest bookCreationRequest) {
CreditCard creditCard = bookCreationRequest.getCreditCard();
ShippingAddress shippingAddress = bookCreationRequest.getShippingAddress();
...
}
With the bookCreationRequest containing the CreditCard and ShippingAddress fields (note: you could use e.g. lombok to reduce the boilerplate code):
public class BookCreationRequest {
private ShippingAddress shippingAddress;
private CreditCredit creditCard;
public ShippingAddress getShippingAddress() {...}
public CreditCard getCreditCard() {...}
public BookCreationRequest(ShippingAddress shippingAddress, CreditCard creditCard) {
this.creditCard = creditCard;
this.shippingAddress = shippingAddress;
}
Which would then expect a request JSON as follows:
POST /checkout/book
Payload:
{
"creditCard": {
...
},
"shippingAddress": {
...
}
}
Note that there can only be a single #RequestBody parameter in a request.
Yes - create a wrapper Request object.
It's not a workaround - it's actually the recommended approach.
You see in your json you have:
{ //wrapper
{}, //first complex data object / mapped to pojo
{} //second complex data object / mapped to pojo
}
1) You can easily apply validation to your Request object with #Valid and hence validate both POJOs.
2) You don't have to worry about the order in the payload.
3) You're using #RequestParam incorrectly. #RequestBody is what maps the whole POST payload. You have to remove the #RequestParam annotation and use #RequestBody instead.
I know this has been asked before, but going through multiple answers did not help me solve my issue. So here it is: I'm a newbie trying to create a REST service using Apache CXF. I'm trying to write a POST method and send the data as JSON in the request body(using POSTMAN in Google Chrome to do this).
My interface looks something like this:
#Path("/")
#Produces("application/json")
public interface MyService{
#POST
#Path("/addNote/{id}")
#Consumes("application/json")
NoteResponse addNote(#PathParam("id") Long id, #QueryParam("note")Note note);
// OTHER #GET METHODS THAT WORK WELL
}
My implmentation:
#WebService(name = "testservice")
public class MyServiceImpl implements MyService{
#Override
public NoteResponse addNote(Long id, Note note){
// SOME IMPLEMENTATION
}
// OTHER #GET METHOD IMPLEMENTATIONS THAT WORK
}
I've read in some answers that I do not need the #QueryParam on my note annotation, instead just put and #XMLRootElement on my Note class, but doing that and trying going on localhost:8080/rest/addNote/1 will NOT call my addNote method.
The problem I am facing now is that the note parameter comes null.
Here's the JSON I've sent via POSTMAN:
{
"note":{
"id": 4958,
"anotherId": 7886,
"comment": "salut",
"mail": "mail#mail.com",
"gregorianDate": "01-01-2016",
"type": "INFO"
}
}
Please try changing your interface definition of API addNote to this:
NoteResponse addNote(#PathParam("id") Long id, Note note);
And send this JSON string via POSTMAN:
{
"id": 4958,
"anotherId": 7886,
"comment": "salut",
"mail": "mail#mail.com",
"gregorianDate": "01-01-2016",
"type": "INFO"
}
This should work.
My question is essentially a follow-up to this question.
#RestController
public class TestController
{
#RequestMapping("/getString")
public String getString()
{
return "Hello World";
}
}
In the above, Spring would add "Hello World" into the response body. How can I return a String as a JSON response? I understand that I could add quotes, but that feels more like a hack.
Please provide any examples to help explain this concept.
Note: I don't want this written straight to the HTTP Response body, I want to return the String in JSON format (I'm using my Controller
with RestyGWT which requires the response to be in valid JSON
format).
Either return text/plain (as in Return only string message from Spring MVC 3 Controller) OR wrap your String is some object
public class StringResponse {
private String response;
public StringResponse(String s) {
this.response = s;
}
// get/set omitted...
}
Set your response type to MediaType.APPLICATION_JSON_VALUE (= "application/json")
#RequestMapping(value = "/getString", method = RequestMethod.GET,
produces = MediaType.APPLICATION_JSON_VALUE)
and you'll have a JSON that looks like
{ "response" : "your string value" }
JSON is essentially a String in PHP or JAVA context. That means string which is valid JSON can be returned in response. Following should work.
#RequestMapping(value="/user/addUser", method=RequestMethod.POST)
#ResponseBody
public String addUser(#ModelAttribute("user") User user) {
if (user != null) {
logger.info("Inside addIssuer, adding: " + user.toString());
} else {
logger.info("Inside addIssuer...");
}
users.put(user.getUsername(), user);
return "{\"success\":1}";
}
This is okay for simple string response. But for complex JSON response you should use wrapper class as described by Shaun.
In one project we addressed this using JSONObject (maven dependency info). We chose this because we preferred returning a simple String rather than a wrapper object. An internal helper class could easily be used instead if you don't want to add a new dependency.
Example Usage:
#RestController
public class TestController
{
#RequestMapping("/getString")
public String getString()
{
return JSONObject.quote("Hello World");
}
}
You can easily return JSON with String in property response as following
#RestController
public class TestController {
#RequestMapping(value = "/getString", produces = MediaType.APPLICATION_JSON_VALUE)
public Map getString() {
return Collections.singletonMap("response", "Hello World");
}
}
Simply unregister the default StringHttpMessageConverter instance:
#Configuration
public class WebMvcConfiguration extends WebMvcConfigurationSupport {
/**
* Unregister the default {#link StringHttpMessageConverter} as we want Strings
* to be handled by the JSON converter.
*
* #param converters List of already configured converters
* #see WebMvcConfigurationSupport#addDefaultHttpMessageConverters(List)
*/
#Override
protected void extendMessageConverters(List<HttpMessageConverter<?>> converters) {
converters.removeIf(c -> c instanceof StringHttpMessageConverter);
}
}
Tested with both controller action handler methods and controller exception handlers:
#RequestMapping("/foo")
public String produceFoo() {
return "foo";
}
#ExceptionHandler(FooApiException.class)
public String fooException(HttpServletRequest request, Throwable e) {
return e.getMessage();
}
Final notes:
extendMessageConverters is available since Spring 4.1.3, if are running on a previous version you can implement the same technique using configureMessageConverters, it just takes a little bit more work.
This was one approach of many other possible approaches, if your application only ever returns JSON and no other content types, you are better off skipping the default converters and adding a single jackson converter. Another approach is to add the default converters but in different order so that the jackson converter is prior to the string one. This should allow controller action methods to dictate how they want String to be converted depending on the media type of the response.
I know that this question is old but i would like to contribute too:
The main difference between others responses is the hashmap return.
#GetMapping("...")
#ResponseBody
public Map<String, Object> endPointExample(...) {
Map<String, Object> rtn = new LinkedHashMap<>();
rtn.put("pic", image);
rtn.put("potato", "King Potato");
return rtn;
}
This will return:
{"pic":"a17fefab83517fb...beb8ac5a2ae8f0449","potato":"King Potato"}
Make simple:
#GetMapping("/health")
public ResponseEntity<String> healthCheck() {
LOG.info("REST request health check");
return new ResponseEntity<>("{\"status\" : \"UP\"}", HttpStatus.OK);
}
Add produces = "application/json" in #RequestMapping annotation like:
#RequestMapping(value = "api/login", method = RequestMethod.GET, produces = "application/json")
Hint: As a return value, i recommend to use ResponseEntity<List<T>> type. Because the produced data in JSON body need to be an array or an object according to its specifications, rather than a single simple string. It may causes problems sometimes (e.g. Observables in Angular2).
Difference:
returned String as json: "example"
returned List<String> as json: ["example"]
Add #ResponseBody annotation, which will write return data in output stream.
This issue has driven me mad: Spring is such a potent tool and yet, such a simple thing as writing an output String as JSON seems impossible without ugly hacks.
My solution (in Kotlin) that I find the least intrusive and most transparent is to use a controller advice and check whether the request went to a particular set of endpoints (REST API typically since we most often want to return ALL answers from here as JSON and not make specializations in the frontend based on whether the returned data is a plain string ("Don't do JSON deserialization!") or something else ("Do JSON deserialization!")). The positive aspect of this is that the controller remains the same and without hacks.
The supports method makes sure that all requests that were handled by the StringHttpMessageConverter(e.g. the converter that handles the output of all controllers that return plain strings) are processed and in the beforeBodyWrite method, we control in which cases we want to interrupt and convert the output to JSON (and modify headers accordingly).
#ControllerAdvice
class StringToJsonAdvice(val ob: ObjectMapper) : ResponseBodyAdvice<Any?> {
override fun supports(returnType: MethodParameter, converterType: Class<out HttpMessageConverter<*>>): Boolean =
converterType === StringHttpMessageConverter::class.java
override fun beforeBodyWrite(
body: Any?,
returnType: MethodParameter,
selectedContentType: MediaType,
selectedConverterType: Class<out HttpMessageConverter<*>>,
request: ServerHttpRequest,
response: ServerHttpResponse
): Any? {
return if (request.uri.path.contains("api")) {
response.getHeaders().contentType = MediaType.APPLICATION_JSON
ob.writeValueAsString(body)
} else body
}
}
I hope in the future that we will get a simple annotation in which we can override which HttpMessageConverter should be used for the output.
Simple and Straightforward send any object or return simple List
#GetMapping("/response2")
#ResponseStatus(HttpStatus.CONFLICT)
#ResponseBody List<String> Response2() {
List<String> response = new ArrayList<>(Arrays.asList("Response2"));
return response;
}
I have added HttpStatus.CONFLICT as Random response to show how to pass RequestBody also the HttpStatus
Annotate your method with the #ResponseBody annotation to tell spring you are not trying to render a view and simple return the string plain