I have a method which returns true or false based on some parameters. So I make an ajax call (using Ext.ajax.request). In spring 2.x version how do I send back the result?
So for my controller I extend BaseSimpleCommandController and override the method
ModelAndView doExecute(HttpServletRequest request, HttpServletResponse response, Object command, BindException errors)
I want to know what would i need to do to send back just a boolean value. I am little confused as what needs to be done. I now i have to send back a ModelAndView type object but nor sure i should i embed a single boolean value in to this object.
EDIT: the BaseSimpleCommandController is specific to my project which in turn extends AbstractCommandController from spring. sorry for the confusion.
If you just want to return "true" or "false" there is no need to use models, command controllers, etc. Simply inject HttpServletResponse and send the data directly:
public void handle(HttpServletResponse response) {
boolean flag = //...
response.getWriter().print(flag);
}
Request params can be mapped via annotation in the method parameter, or through the request's parameter map
Method Parameter:
#RequestMapping(method=RequestMethod.GET)
public void someCall(#RequestParam(value="param1") String paramName)
...
Where param1 would be the get parameter param1. If you don't provide a value for the annotation, it tries to bind to the name of the parameter in the method name (paramName in this case).
Parameter Map
#RequestMapping(method=RequestMethod.GET)
public void someCall(HttpServletRequest request)
{
Map<String, String[]> paramMap = request.getParameterMap();
}
Hope this helps!
Related
getParameterMap() of HttpServletRequest returns both the query params and posted form data.
I am able to fetch the query parameters alone from UriInfo.getQueryParameters().
But I need the form parameters separately as a MultivaluedMap similar to query parameters, is there a way to fetch it?
EDITED:
I apologize for not making this clear. I am trying to fetch the form parameters in the filter/interceptor.
You can put the MultivaluedMap as a parameter in the resource method. This will be the body of the request. JAX-RS will put all the parameters in the map for you.
#POST
#Consumes("application/x-www-form-urlencoded")
public Response post(#Context UriInfo uriInfo, MultivaluedMap params) {}
UPDATE (to edited post)
So if you want to get the parameters in a filter, you can get the body from the ContainerRequestContext. With Jersey, instead of getting the InputStream with context.getEntityStream(), you can cast the ContainerRequestContext to Jersey's ContainerRequest implementation. This will give you access to the methods bufferEntity() and readEntity(). These methods will allow you do easily get the form parameters. You will need to buffer the entity so that it can be read later when it needs to be passed on to your resource method.
#Provider
public class MyFilter implements ContainerRequestFilter {
#Override
public void filter(ContainerRequestContext context) throws IOException {
if (MediaTypes.typeEqual(MediaType.APPLICATION_FORM_URLENCODED_TYPE, context.getMediaType())) { {
return;
}
ContainerRequest request = (ContainerRequest) context;
request.bufferEntity();
Form form = request.readEntity(Form.class);
MultivaluedMap params<String, String> = form.asMap();
MultivaluedMap<String, String> query = context.getUriInfo().getQueryParameters();
}
}
If you want to use the filter only with specific resource methods, then you can use Name Binding or Dynamic Binding.
If for some reason the readEntity() returns an empty map (I've seen rare occurrences of people having this problem), you can try to retrieve the Form through an internal property
Object formProperty = request.getProperty(InternalServerProperties.FORM_DECODED_PROPERTY);
if (formProperty != null) {
Form for = (Form) formProperty;
}
The idea is, I receive POST request with some parameters already included
e.g., car name and price
I need to add some parameter that client should not know about (for example, car's VIN, which client should not know before he makes a purchase)
Then, with parameter added, I want to forward this request to another site, which all data that I have passed (car name, price, vin)
Is there a way to implement on Controller level, not filters?
#RequestMapping(value = "/abc")
public void ABC(final HttpServletRequest request) {
request.getParameterMap().put("vin", VIN_CODE); // cannot do that because it is read-only
return "forward:https://completelyanothersite.com";
}
EDIT: Based on comments, forwarding is not solution, instead redirecting is the one
The little-less dirty (that I know of) way to do that is by extending the request:
public class WrappedHttpServletRequestWrapper extends HttpServletRequestWrapper
{
private final Map<String, String[]> modifiableParameters;
private Map<String, String[]> allParameters = null;
public WrappedHttpServletRequestWrapper (final HttpServletRequest request,
final Map<String, String[]> additionalParams)
{
super(request);
modifiableParameters = new TreeMap<String, String[]>();
modifiableParameters.putAll(additionalParams);
}
#Override
public Map<String, String[]> getParameterMap()
{
// allParameters contains old parameters + the ones you added
return Collections.unmodifiableMap(allParameters);
}
//... other overriden methods
}
And use that one to add your parameters. Here is the reference.
And here is how you will use it:
Map<String, String[]> extraParams = new TreeMap<String, String[]>()
HttpServletRequest wrappedRequest = new WrappedHttpServletRequestWrapper(request, extraParams);
request.getRequestDispatcher("url").forward(wrappedRequest, response);
Spring MVC provides a powerful set of features to automatically parse and map HTTP requests and responses for you so you don't have to do it manually and can focus on business logic. In this case, Spring can hand you a map of all request parameters like this:
#PostMapping("/abc")
public void abc(#RequestParam Map<String, String> params) { ... }
(or, if you need multi-valued parameters, you can use MultiValueMap, which is slightly more standards-correct but a bit more complicated to work with). You get a private copy of the map, which in practice is a mutable LinkedHashMap, but if you're ever unsure you can always just say new HashMap<>(params).
Once you have this params map, you can add whatever additional values you want to it, but unless you can send someone to another controller inside your own application you'll need to either generate a redirect: response (in which case the VIN will be visible in the URL) or make a REST request yourself to the other service and then relay the information back to the user.
You can send a redirect to another website, but can not forward it to another website.
Use resp.sendRedirect(url);
Refer this thread Difference between JSP forward and redirect
I have a Spring controller that as return a redirection to another controller.
First looks like this
#RequestMapping(value = "/some-url", method =
{ RequestMethod.POST, RequestMethod.GET })
public String test(final Model model)
{
...
return "redirect:http://someurl/checkout/response";
}
The second is hooking the call of the first controller so it looks like this:
#RequestMapping("/**/response")
public String handleResponse(#RequestParam final MultiValueMap<String, String> params, #Valid #ModelAttribute final Cyber cyber,
final BindingResult bindingResult, final Model model, final HttpSession session, final HttpServletRequest request) throws CMSItemNotFoundException...
I am wondering how to pass the '#RequestedParam params' and the Cyber object from the first controller to the second.
If you additionally want these attributes to be erased automatically from the session after they where consumed, you can alternatively use FlashAttributes. For this you have to declare a RedirectAttributes parameter in method handleResponse and call addFlashAttribute on it. For example addFlashAttribute("cyber", cyber). Those will be available as model attributes in the targeted controller and will be gone out of the session automatically.
You can use #SessionAttributes and send the model to another content.
For more click here
Hi thank you guys I found a solution googleing your suggestion in this link :
http://www.concretepage.com/spring/spring-mvc/spring-mvc-redirectview-example-add-fetch-flash-attributes-redirectattributes-model-requestcontextutils
This is exactly my case.
I'm new to Jersey, and want to determine the #Produces type in other contexts, so I can use it during error handling cases.
For example, I have the following method that produces json:
#Path("test-json")
#Produces(MediaType.APPLICATION_JSON)
#GET
public Object getTestJson(#Context HttpServletRequest req, #Context HttpServletResponse res) throws Exception
{
throw new RuntimeException("POST submitted without CSRF token! ");
}
Later on, in a global exception handler, I'd like to get the #Produces media type.
I've tried doing this with something like the following, but getMediaType() is returning null (note that this is simplified, but headers is not null in all of my tests, just getMediaType() is null).
public class someClass
{
#Context
HttpHeaders headers;
public Response convertExceptionToResponse(T exception)
{
MediaType mediaType = headers.getMediaType();
// At this point, I thought media type would be
// MediaType.APPLICATION_JSON
// for the above 'getTestJson' method, but it's null.
}
}
How can I do this?
JAX-RS
Inject ResourceInfo and invoke getResourceMethod() which will return Java Method. Then you can simple retrieve declared annotations. The problem here is that with this approach you need to do a lot of coding in case #Produces is not located directly on a method but somewhere in the hierarchy.
Jersey 2
Inject ExtendedUriInfo
#Context
private ExtendedUriInfo uriInfo;
and look for matched ResourceMethod (getMatchedResourceMethod()). Then simply get list of producible media types (getProducedTypes()).
How can I easily separate JSON values that are sent in the same request?
Given that I POST a JSON to my server:
{"first":"A","second":"B"}
If I implement the following method in the Controller:
#RequestMapping(value = "/path", method = RequestMethod.POST, consumes = MediaType.APPLICATION_JSON_VALUE)
public void handleRequest(#RequestBody String input) {
// ...
}
then the input parameter will constitute a String with the entire JSON object, {"first":"A","second":"B"}. What I really want is two separate Strings (or a String and an int whichever is suitable for the particular request) with just the two values (other key / value pairs that the client may send should be ignored).
If the strings were sent as request parameters instead of JSON request body it would be simple:
#RequestMapping(value = "/path", method = RequestMethod.POST)
public void handleRequest(#RequestParam("first") String first,
#RequestParam("second") String second) {
// ...
}
I know that I can create a simple bean class that can be used in conjunction with the #RequestBody annotation that will contain both A and B when used, but it seems like a detour, since they will have different purposes inside the web app.
Dependencies:
org.springframework : spring-web : 3.1.0.RELEASE
org.codehaus.jackson : jackson-mapper-asl : 1.9.3
POJO
public class Input {
private String first;
private String second;
//getters/setters
}
...and then:
public void handleRequest(#RequestBody Input input)
In this case you need Jackson to be available on the CLASSPATH.
Map
public void handleRequest(#RequestBody Map<String, String> input)
I have written a custom WebArgumentResolver that does exactly this, combined with a custom annotation.
I don't have the source available to me now, but basically I annotated my method like this:
#RequestMapping(value = "/path", method = RequestMethod.POST)
public void handleRequest(#JsonField("first") String first, #JsonField("second") String second) {
// ...
}
Then my JsonFieldWebArgumentResolver checks if the method parameter is annotated with JsonField, and if it is it extracts the actual type from the parameter (not quite straight-forward it turns out if you want to handle generic parameters as well, such as List<String> or List<Pojo>), and invokes Jackson's JsonParser manually to create the correct type. It's a shame I can't show you any code, but that's the gist of it.
However, that solution is for Spring MVC 3.0, and if you are using 3.1 I think you will be better off using a custom HandlerMethodArgumentResolver instead. But the idea should be the same.