How to re-write request URI along with path variable in Spring? - java

I'm using Spring 4 right now and I have a controller defined a such:
#RequestMapping(value = "/{id}/definitions", method = RequestMethod.PUT)
#ResponseBody
public List<ResponseDTO> update(#PathVariable(value = "id") String id,
HttpServletRequest iRequest) throws Exception
{ ... }
I am expecting to receive an encrypted 'id' String coming as part of a path variable in the request itself. But what I need to do is re-write this request URI and decrypt it to another value (an integer, for example) and form another HTTP request with the original URI only with the transformed/decrypted value.
How can I get a hold of the entire URI and substitute the {id} with an integer?
For example, if the original request coming in looks like:
http://mycompany.com/my-service/kjAISOhalkjZjakmbbb/definitions
I want to transform everything after the context path:
/kjAISOhalkjZjakmbbb/definitions
to:
/123456/definitions
So finally, I can form a request to another service that might look like this:
http://mycompany.com/my-service-2/123456/definitions
Thank you!

Decrypt the value (however you do that).
Then just use a redirect or forward (probably a forward in your case):
#RequestMapping(value = "/{id}/definitions", method = RequestMethod.PUT)
public void update(#PathVariable(value = "id") String id,
HttpServletRequest iRequest) throws Exception {
String decryptedId = //decrypt here
//Do whatever else
//either forward: or redirect:
return "forward:my-service-2/" + decryptedId + "/definitions";
}

Related

How i can pass a list<String> to the server with url

I am trying to pass the List of String from one server to the another server in spring boot.
How i can get that list at the another server?
The code i have tried-
public void addNewMostPopular(List<String> totalList){
try {
HttpHeaders httpHeaders = getHttpHeaders();
HttpEntity<String> httpEntity = new HttpEntity<String>(null, httpHeaders);
ResponseEntity responseEntity = restTemplate.exchange(
BASE_URL + "addMostPopular/"+new ArrayList<>(totalList), HttpMethod.POST, httpEntity,TrendingCategoryDTO.class);
}
and at server side i tried to get like-
#RequestMapping(value="/addMostPopular/[{totalList}]", method = RequestMethod.POST)
public void addMostPopularProduct( #PathVariable List<String> totalList) {}
Past long object in the url is a bad praxis, thats because spring url interpreter has a maximun lenght, so if you pass more than 2048 or 4096 char in some cases your request will return Response 400 bad request and won't execute anycode on your spring server.
After this aclaration, is there any option to pass a list? Yes, of course! But we need use #RequestBodylike this:
#PostMapping("/addMostPopular")
public void addMostPopularProduct(#RequestBody List<String> totalList) {
// Your function
}
Now we need to add to our other server the List we want to pass to this request in the body of the request.
If you like to pass a List of values in the url one possibility is to pass them as url parameters.
You have to create a link similar to the followings:
http://youserver/youraction?param=first&param=second&param=third
or
http://youserver/youraction?param=first,second,third
Your controller in spring must be something like
#Controller
public class MyController {
#GetMapping("/youraction")
public String yourAction(#RequestParam("param") List<String> params) {
// Here params is tre list with the values first, second, third
}
}
This action is able to handle both kind of requests that I wrote before.
There are many ways to pass infomation between servers.
The simple way is to initiate an http request, based on your request method get or post put the parameters to the appropriate location : reuqest header or request body. You can do like #Davide Lorenzo MARINO.
Or use a message queue, like ActiveMq.
In the case of the same registry center, you can also use #feign to resolve it.

Correct way to put parameters in a function

I have a huge form with around 30 parameters and I don't think it's a good idea to do what I usually do.
The form will be serialized and pass all the parameters via ajax post to spring controller.
I usually do like this:
#RequestMapping(value = "/save-state", method = RequestMethod.POST)
public #ResponseBody
void deleteEnvironment(#RequestParam("environmentName") String environmentName, #RequestParam("imageTag") String imageTag) {
//code
}
but if I have 30 parameters I will have a huge parameter list in the function.
What is the usual and correct way to avoid this?
EDIT: What if I pass the HttpServlet request only?? The request will have all the parameters and I can simple call request.getParameters("").
There are two options I would suggest:
Take an HttpServletRequest object and fetch needed properties separately.
The problem is Spring's controllers are designed to eliminate such low-level API (Servlets API) calls. It's could be the right fit if a controller was too abstract (operates on abstract datasets), which means you wouldn't be able to define a DTO with a fixed-length number of parameters.
Construct a DTO class with the properties needed and take it as a parameter.
The advantage is you completely delegate low-level work to Spring and care only about your application logic.
You can do something like this:
#RequestMapping(value = "/save-state", method = RequestMethod.POST)
public void deleteEnvironment(#RequestBody MyData data) {
//code
}
Create a class containing all your form parameters and receive that on your method.
but if I have 30 parameters I will have a huge parameter list in the
function.
In your request, pass a JSON object that contains these information and create its counterpart in Java.
RequestMethod.POST is not design to perform deletion.
Usr rather RequestMethod.DELETE.
#RequestMapping(value = "/save-state", method = RequestMethod.DELETE)
public #ResponseBody
void deleteEnvironment(MyObject myObject) {
//code
}
Correct way is to serialize all parameters as Json and call back end api with one parameter.
On back-end side get that json and parse as objects.
Example:
` #RequestMapping(method = POST, path = "/task")
public Task postTasks(#RequestBody String json,
#RequestParam(value = "sessionId", defaultValue = "-1") Long sessionId)
throws IOException, AuthorizationException {
Task task = objectMapper.readValue(json, Task.class);
`

Determine route in multi route controller method

That defines multi route method in controller in Spring MVC
#RequestMapping(value={"/path", "/path2"}, method = RequestMethod.GET)
public String MyMethod () {
// Determine which route invoked the method
return null;
}
Is there a way to determine which route invoked the method?
Appreciate your kind help.
You could use HttpServletRequest which has a method called getRequestURL() to retrieve the actual URL, allowing you to parse which path was used.
However, another possibility is using path variables instead:
#RequestMapping(value = "/{path}", method = RequestMethod.GET)
public String myMethod(#PathVariable String path) {
// Do stuff with "path"
return null;
}
In this case, the path variable will contain whatever you enter matching the path given in your #RequestMapping, in your case it would be "path" or "path2". However, this will also allow other path variables as well ("path3" for example, ...), so you might want to validate it first before using.
I believe you can use HttpServletRequest:
#RequestMapping(value={"/path.html", "/path2.html"}, method = RequestMethod.GET)
public String MyMethod (HttpServletRequest request) {
// Determine which route invoked the method
String url = new String(request.getRequestURL());
log.debug("URL: " + url); //use whatever you use to log
return null;
}

Spring MVC N number of parameters mapping

I tried binding N numbers of parameters in a URL like this
/web/appl/<applname>/rule/<rulename>/<attrname1>/<attrval1>/<attrname2>/<attrval2>/.../<attrnameN>/<attrvalN>
with
#RequestMapping(value = "/web/appl/{applname}/rule/{rulename}/{attributes}", method = RequestMethod.GET)
public Object GetService(HttpServletRequest request, #PathVariable("attributes") Map<String, Object> map,
#PathVariable("applname") String applname, #PathVariable("rulename") String rulename)
throws Exception {
...
}
but could not get values of <attrval1>/<attrname2>/<attrval2>/.../<attrnameN>/<attrvalN>
Unfortunately Spring MVC does not provide such a solution. You can consider the Matrix Variables as an alternative.
If you prefer sticking to your current URI scheme then you have to implement a solution yourself. One approach is to use a path pattern. Example:
#RequestMapping(value = "/web/appl/{applname}/rule/{rule name}/**")
public Object getService(HttpServletRequest request,
#PathVariable("applname") String applname ...) {
String attributesPart = new AntPathMatcher()
.extractPathWithinPattern("/web/appl/{applname}/rule/{rule name}/**",
request.getServletPath());
...
You could implement your argument resolver that does that. Something like
#RequestMapping(value = "/web/appl/{applname}/rule/{rule name}/**")
public Object getService(#MyAttributes Map<String, String> attributes,
#PathVariable("applname") String applname ...) {
Use
String urlAttributes = (String) request.getAttribute(HandlerMapping.PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE);
and get whole URL. After that parse this URL according to your needs like if you did not get
<attrval1>/<attrname2>/<attrval2>/.../<attrnameN>/<attrvalN>
in proper sequence then you can throw exception.

sending variable back to server in spring mvc

I am trying to reload the same page with different content that varies depending on which link is clicked on the page. The url pattern for the page is "/owners", which triggers the running of this method in OwnerController.java:
#RequestMapping(value = "/owners", method = RequestMethod.GET)
public String processFindForm(Owner owner, BindingResult result, Map<String, Object> model) {
Collection<Owner> results = this.clinicService.findOwnerByLastName("");
model.put("selections", results);
model.put("sel_owner",this.clinicService.findOwnerById(ownerId));//ownerId is not defined yet
return "owners/ownersList";
}
The jsp includes a dynamically generated list of ownerId integer values, each of which can be used to send a unique ownerId back to the server. What do I need to add to my jsp in order to get ownerId to have a user-specified value when processFindForm() is run? In other words, what does the hyperlink need to look like?
You are using GET request type.If you want to send any parameter to controller then you have to use either #RequestParam or #PathParam annotations based on requirement as an arguments to controller method. In your case it will be something like...
public String processFindForm(#RequestParam("ownerID") String ownerId, BindingResult result, Map<String, Object> model) {... }
Take a look on this link as well: http://www.byteslounge.com/tutorials/spring-mvc-requestmapping-example

Categories