Spring MVC requests processing order - java

I have a web service that receives some data from clients and saves them to a Map
#Controller
public class ExampleController {
private final Map<String, String> state = new ConcurrentHashMap<>();
#RequestMapping(value = "/set-state", method = RequestMethod.POST)
public synchronized #ResponseBody void setState(#RequestParam String id,
#RequestBody String updatedData) {
state.put(id, updatedData);
}
}
Suppose that a client sends two requests one after another. Both requests have the same id, but the second request has updated data.
The question is, does Spring MVC guarantee that setState will be called with request 1 data first? Is making the method synchronized enough to make sure I'll always get the updated data from request 2 in the state Map?

Related

How to call rest API in the loop

I want to call the third party API multiple times using the RestTemplate(for each customer id I have to call REST API) currently I have written like below and its working fine but it's taking time because there are many customers I'd and calling API for each customer id, is there any way I can make this parallel.
public List<Organization> getCustomeOrganizationInfo(){
String url="https://url.net/core/v1/customers"
List<Organization> organizationList = new ArrayList<>();
for(Customer customer:CustomerList){
String restUrlWithUserId=url+"/customer.getCustomerId"
CustomerInfo customerInfo = restTemplate.exchange(
restUrlWithUserId,
HttpMethod.GET,
request,
String.class
);
Organization organization =new Organization();
organization.setCustomerId(customer.getCustomerId())
organization.setorganizationId(customerInfo.getCustomeOrganizationId())
organization.setorganizationname(customerInfo.getCustomeOrganizationName())
organizationList.add(organization)
}
}
Is there any way I can make this parallel
For concurrency and clean code, you should separate your restTemplate call to another class(service), for example, ThirdPartyCustomerService.java. This class will be held responsible for calling outside.
#Service
public class ThirdPartyCustomerService {
private final RestTemplate restTemplate;
private final String url = '...';
...
public CustomerInfo getCustomerInfo() {
return this.restTemplate...
}
}
Then you can inject this class into your service class. Now if you want to run it concurrency. You could try #Async and Future here. Just need a little bit of change on the new service and remember to call Future.get() on your main service.
#Async
public Future<CustomerInfo> getCustomerInfo() {
return new AsyncResult<CustomerInfo>(this.restTemplate...);
}
Or you can use WebClient, an alternative for RestTemplate and AsyncRestTemplate.

How to map a request in Spring MVC to a Java Object

I'm new to Spring, and since Spring provides many ways to map an HTTP request to Java objects, I'm hoping someone could advice me how to resolve this:
I have a client that sends a request having
ContentType: application/x-www-form-urlencoded
Some of the request parmeters have names such as
"form_data[orderStatus]", "form_data[orderNumber]", etc'
I have no control over this client!
I have a java class (#Component) called MyOrder which looks as follows:
#component
#Scope("prototpe")
public class MyOrder {
private String orderStatus;
private String orderNumber;
//etc'
public void setOrderStatus(String orderStatus) {
this.orderStatus = orderStatus;
}
//public setter for all other properties, as the above
}
What is the simplest way to create an instance of MyOrder
populated with all values of all "form_data[]", so that I can have a controller method having a signature that includes a MyOrder parameter, such as:
public ModelAndView saveNewOrder( #RequestParam("foo") String foo,
#ModelAttribute("myOrder") MyOrder anOrder) {
//... impl'n here
}
The best solution I could think of was to use a Web Filter which would flaten request params names such as "form_data[attrib1]" to "attrib1", and then Spring would do all the work of populating the MyOrder instance.
One disadvantage of this is that the request may have both "form_data[attrib1]" and "attrib1" parameters. For example:
form_data[orderStatus]=ok
orderStatus=fail
In this case i want MyOrder.orderStatus to have the value "ok".
Any good way of utilizing Spring create MyOrder from the request?
As an alternative, that does not use the class MyOrder, is there a way to have Spring map all the form_data[] parameters and their values to a map, so that i can have the controller method below?
public ModelAndView saveNewOrder( #RequestParam("foo") String foo,
<some annotation> #Map<String,String> formFieldsOfAnOrder) {
//... impl'n here
orderStatus = formFieldsOfAnOrder.get("orderStatus");
//or at least:
orderStatus = formFieldsOfAnOrder.get("form_data[orderStatus]");
}

How to provide a list of objects for a REST query in spring-mvc?

I want to create a REST-GET controller in spring-mvc that takes a list of objects, eg 10 ids as follows:
#RestController
public class MyRest {
#RequestMapping(method = RequestMethod.GET)
public Object test(#RequestParam value="id" required=false) List<Integer> ids) {
Sysout(ids);
}
}
Anyway when I call it, I have to repeat the id param multiple times:
localhost:8080/app?id=1&id=2&id=3&...
It is possible to change the param to some kind of list? Eg
app?id=1,2,3,4,5
And if yes, is this advisable? What's better from the client point of view?
Its better to use POST message with JSON or XML as request body.
As you never know how many id's will be passed.
#RestController
public class MyRest {
#RequestMapping(method = RequestMethod.POST)
public Object test(#RequestBody IDRequest request) {
Sysout(ids);
}
public static final class IDRequest {
List<Integer> ids;
<!-- getter/setters--->
}
}
where the request will be some kind of a JSON or XML like this
{"ids":[1,2,3,4,5,6,7,8,9]}
You can provide list of objects to rest service as request param.Here is the example
#RequestMapping(value = "/animals, method = RequestMethod.GET)
public void test(#RequestParam(value="animalsNames[]") String[] animalsNames) {
Sysout(animalsNames);
}
And your request looks like
http://localhost:8080/appname/animals?animalsNames[]=dog,horse
HTTP Method type : GET
Controller :
public #ResponseBody String getInfos(HttpServletRequest request,
#RequestParam #DateTimeFormat( #RequestParam List<Long> ids) {...}
Request :
http://localhost:8080/test/api?ids=1,2,3

How to use #Inject in Spring MVC Controller?

I am working with Spring MVC controller. I have one of my controller as DataController.
I am thinking to add HttpServletRequest as injectable at the top of DataController class using #Inject.
#Controller
public class DataController {
#Inject
HttpServletRequest request;
// .. some code here
#RequestMapping(value = "process", method = RequestMethod.GET)
public #ResponseBody
DataResponse processTask(#RequestParam("workflow") final String workflow) {
String ipAddress = request.getRemoteAddr();
System.out.println(ipAddress);
}
So my question is - Is this the right way to use #Inject? I have never used #Inject before so trying to learn whether the way I am doing it is right or not? Since everytime, who is making call to processTask method, I need to grab its ipAddress whoever is calling that processTask method.
In terms of acquiring HttpServletRequest: semantically speaking, it is definitely wrong.
Reason: HttpServletRequest is an object that is created only when users send requests and is destroyed once the requested user action is completed. You simply can store it that way (from syntax angle) but you shouldn't (from semantic angle). You need to realize that the way how web application works is not exactly same as a desktop application (and don't observe them from the same angle).
Suggestion:
#RequestMapping(value = "process", method = RequestMethod.GET)
public #ResponseBody
DataResponse processTask(#RequestParam("workflow") final String workflow, HttpServletRequest request) {...}
In this way you will get the corresponding request each time the processTask method is called. (HttpServletRequest object is injected by #RequestMapping.)
(If you would like to preserve something through out a session, consider use a bean that is
Suggestion: #Inject private UserService userService;
(assume we have a class registered called UserService.)
You cannot "inject" the HttpServletRequest the only way to use it as far as I know is to added as a method member. Like this:
#Controller
public class DataController {
// .. some code here
#RequestMapping(value = "process", method = RequestMethod.GET)
public #ResponseBody
DataResponse processTask(#RequestParam("workflow") final String workflow,HttpServletRequest request) {
String ipAddress = request.getRemoteAddr();
System.out.println(ipAddress);
}
look also at Spring MVC #AutoWired response not working

Getting original request in a REST method( springframework )

Is there a way to get the http request (header content) in a REST method? I'm using spring framework.
I want to build a new request from the current request to a different server in the REST method. This is more like a proxy/forwarding service - so I want to preserve the stuff I want in the original request.
I do not have much options -otherwise I would not have used REST for such stuff.
Does spring framework provide such interface?
For example - if I want to get hold of the request headers in the greeting method in the code below ( example code from spring.io )
#Controller
public class GreetingController {
private static final String template = "Hello, %s!";
private final AtomicLong counter = new AtomicLong();
#RequestMapping("/greeting")
public #ResponseBody Greeting greeting(
#RequestParam(value="name", required=false, defaultValue="World") String name) {
return new Greeting(counter.incrementAndGet(),
String.format(template, name));
}
}
You can simply give your handler method a parameter of type HttpServletRequest and Spring will provide it for you.
#RequestMapping("/greeting")
public #ResponseBody Greeting greeting(
#RequestParam(value="name", required=false, defaultValue="World") String name,
HttpServletRequest request) {
HttpServletRequest provides a number of methods to retrieve HTTP headers.
Alternatively, Spring also provides the #RequestHeader annotation that can be used like #RequestParam to retrieve a header from the HTTP request.

Categories