I have this method in my Controller that returns a json string to the view
#RequestMapping(value = "/getDevs", method=RequestMethod.GET)
public#ResponseBody String getDevs() throws JsonProcessingException,RemoteException,ServiceException{
ObjectMapper om = new ObjectMapper();
return om.writeValueAsString(WSCall.getDevelopers());
}
I call the method URL using ajax. Everything works fine except I can obtain the json if I put the URL directly in the browser. Is there a way to block this?
I agree with the comments above, that it is not relevant from a security standpoint, but you could probably make use of the X-Requested-With: XMLHttpRequest header that is most likely set for your AJAX requests. I can at least confirm it for jQuery, which might be on your tool stack.
So you could add the headers parameter to your #RequestMapping annotation:
#RequestMapping(value = "/getDevs", method=RequestMethod.GET, headers = { "X-Requested-With=XMLHttpRequest" })
public#ResponseBody String getDevs() throws JsonProcessingException,RemoteException,ServiceException{
[...]
}
Related
I'm working on a stubbing tool where a user can provide a list of endpoints and their associated JSON response. The idea is they will include a config file containing URIs and a directory of all stubbed responses. So essentially the config file will include the list of URI's that typically would be set using #RequestMapping if this was being built for a specific use case. Is there a way to have Spring send a success response even if the associated #RequestMapping doesn't exist?
Something similar to a SQL query e.g.
#RequestMapping(value = "/*", method = arrayOf(RequestMethod.POST))
fun sendResponse() : ResponseEntity<String> {
//Fetched correct response from interceptor
return ResponseEntity<String>
}
Found out the answer. You need to use #RequestMapping(value = "/**", method = arrayOf(RequestMethod.POST)).
How i can access to request POST data from different url-s to one controller method, for example I have /countries & /countries/{id} URL, It works very good with first one, because my code is
#RequestMapping(value = {"/{id}", "/{id}/"}, method = RequestMethod.GET)
public String getCountry(#PathVariable(value = "id", required = true) int id,ModelMap model) {
}
#RequestMapping(method = RequestMethod.POST)
public String deleteCountry(ModelMap model,HttpServletRequest request) {
}
And when I try to request POST data from second url I'm getting
HTTP Status 405 - Request method 'POST' not supported
Which is expectable because I haven't POST method with this mapping, but if I will be made one method for one mapping my code will be too ugly ant terrible, what solution I can use?
Hum why not add the "array" of value to your second method as well ?
#RequestMapping(value = {"", "/{id}"},method = RequestMethod.POST)
public String deleteCountry(ModelMap model,
HttpServletRequest request) {
Btw using POST verb to call an action that looks like it will delete the resource seems wrong, it should be a DELETE verb used
EDIT
But in reality, you should be creating 2 methods, as both those method are not supposed to do the same thing.
POST /countries should be creating country resources
POST /countries/{id} should be doing something else.
For an update prefer PUT /countries/{id}
And for a delete, prefer DELETE /countries/{id}
There is one way to have separate handler interceptors for different controllers.
Refer this link for details.
bind Spring HandlerInterceptor only to one controller
But I feel, it may be good you can create a common method to share business logic for this.
As Interceptor comes with proxy class for your controller which can be avoided unless you have complex logic.
I am using Spring 4.1 framework for developing webservices. When I return a Java object as response, it is automatically converted to JSON and delivered to client, so I assume that JSON parser is in classpath and it is configured properly. However it fails to convert the request body from JSON into Java object and client is getting a HTTP response of 400.
Here is how the webservice looks like:
public class Details{
public Details(){
}
int code;
int area;
}
#RequestMapping(value = "/api/update/{phoneNumber}", method = RequestMethod.POST, consumes = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<String> update(#PathVariable final String phoneNumber, #RequestBody Details details)
Here is how the request looks like:
Method: Post
Content-Type: application/json; charset=utf-8
Body: {"code":0,"area":12}
If I collect the request body as string and parse it manually then it works, so it gets the valid JSON but for some reason it is not parsing it automatically. I have no clue on how to fix it. Please help. Thanks in advance.
You have package-private properties in your Details class, so they are probably not recognised by json-converter.
You have several options:
define them as public (not recommended)
provide getters and setters
if you are using jackson, you can annotate them with #JsonProperty, leaving them package-private
Finally I got the reason for this. I was using inner classes which were not static. Making those static fixed the issue.
I have a Spring MVC controller for a RESTful resource (ServiceDirectoryController), which I want to serve both HTML (web page) and non HTML (web service) representations. I want to use view names and JSP to generate the HTML representation, but HttpMessageConverters for the other representations. How do I do that?
I've implemented the request handling method for the non-HTML representations. My internal (domain-model) representation is ThingNames, for which I have suitable message converters, so the request handling method is simply:
#RequestMapping(value = { "/directory/" }, method = RequestMethod.GET)
#ResponseBody
public ThingNames retrieveThings() {
...
}
Now I want to add the request handling method for the JSP page. So I need a method that indicates the view name and provides a suitable model. So, the obvious thing to do is this:
#RequestMapping(value = { "/directory/" }, method = RequestMethod.GET)
public String retrieveThings(Map< String, Object > model) {
...
}
with the view name as the return value.
But will that work? Is Spring clever enough to work out that the HTML representation should be handled by the second method, and use the first method for all other representations? And if not, how do I go about handling both JSP/HTML and non JSP/HTML representations?
According to a Spring blog post by Paul Chapman, my controller will work as written if I set up a PPA Content Negotiation Strategy. That is, if I configure Spring to consider clues about the wanted content type in the following descending order of preference:
Path extension (.htm, .tsv, etc.)
Request parameter (?format=htm, ?format=xls)
Accept header (proper HTTP content negotiation, which sadly works poorly with HTML browsers).
What is more, the Spring provided ContentNegotiationManagerFactoryBean operates in just that order.
In addition, you must annotate the handler methods in the controller so Spring knows that those methods should handle HTML content, using the consumes and produces values of the #RequestMapping annotation. That is, instead of simply writing
#RequestMapping(value = { "/directory/" }, method = RequestMethod.GET)
#ResponseBody
public String retrieveThings(Map< String, Object > model) {
...
}
write
#RequestMapping(value = { "/directory/" }, method = RequestMethod.GET,
produces = MediaType.TEXT_HTML_VALUE)
#ResponseBody
public String retrieveThings(Map< String, Object > model) {
...
}
I build my web application based on Spring MVC and come across a problem whilst trying to add a cookie in a method handling an ajax request.
I realized that method with #ResponseBody (in my example it returns a string value) does not create a "real" response and added cookies are lost.
Is there any way to add a cookie in a method called via ajax (and therefore annotated with #ResponseBody) in Spring MVC?
You can use the following signature to do this
#ResponseBody
public String x((HttpServletRequest request, HttpServletResponse response){
Cookie userCookie = new Cookie("<name>", "<valie>");
//set other cookie properties
response.addCookie(userCookie);
return "xxx";
}