Spring URL mapping question - java

I am using Java with Spring framework. Given the following url:
www.mydomain.com/contentitem/234
I need to map all requests that come to /contentitem/{numeric value} mapped to a given controller with the "numeric value" passed as a parameter to the controller.
Right now in my servlet container xml I have simple mappings similar to the following:
...
<entry key="/index.html">
<ref bean="homeController" />
</entry>
...
I am just wondering what I need to add to the mapping in order to achieve what I described?
Edit: I unaccepted the answer temporarily because I can't seem to figure out how to do the mapping in my web.xml (I am using annotations as described in axtavt's answer below). How do I add a proper <url-pattern>..</url-pattern> in my <servlet-mapping> so that the request for "/contentitem/{numeric_value}" gets properly picked up? Thanks!

It can be done using annotation-based controller configuration (see 15.3 Implementing Controllers):
#Controller
public class ContentItemController {
#RequestMapping("/contentitem/{id}")
public ModelAndView contentItem(#PathVariable("id") int id) {
...
}
}

try to use #RequestMapping and #PathVariable
#RequestMapping(value="/contentitem/{value}", method=RequestMethod.GET)
public String demo(#PathVariable(value="nvalue") String name, ModelMap map) {
int intValue = Integer.parseInt(nvalue);
// Do manipulation
return "something"; // Forward to something.jsp
}
Watch this Spring MVC Framework Tutorial

You must import org.springframework.stereotype.Controller.

Related

Generating json using spring-mvc

I tried to generate a json response earlier using spring-mvc (annotation) . After so may failure i find out some check point :
I need to add <mvc:annotation-driven/> in my servelet mapper. although i don't know the reason.
Then I need to add #ResponseBody annotation which should bound the return value as http response as the documentation says.
And I also need add some jacson dependency.
Did i missed something?
Now i have bunch of questions
why we have to add that in my servelet xml and how this whole process is working?
As json response is most commonly used when why spring need jackson dependency to generate json?
some days ago i was doing Struts2 generating json response there was much simple.
Is there any way to do it more easily in spring-mvc .?
At first you should understand that <mvc:annotation-driven/> annotation used for many cases not only for generating json response in Spring. This annotation allow to use different annotations in Spring mvc classes like:#NumberFormat #DateFormat #Controller #Valid and of course #ResponseBody.
To generate json response you just need #ResponseBody annotation in your controller or servlet and import libraries for processing JSON.
Recently java has oun set of APIs for processing JSON as part of Java EE 7 JSR 353 actually it has clean Oracle tutorial. Also you can use third party libraries like Jackson. To process (parse, generate, transform, and query) JSON text it's necessarily to have one of this libs.
You can learn about most popular third party libraries and their performance in this article
Here you can see simple example.
If you are using jacson you can do something like:
Your Model
public class Shop {
String name;
String staffName[];
}
Your Controller
#Controller
#RequestMapping("/shop/list")
public class JSONController {
#RequestMapping(value="{name}", method = RequestMethod.GET)
public #ResponseBody Shop getShopInJSON(#PathVariable String name) {
Shop shop = new Shop();
shop.setName(name);
shop.setStaffName(new String[]{"mkyong1", "mkyong2"});
return shop;
}
}
mvc-dispatcher-servlet.xml
<context:component-scan base-package="com.example.mypackage" />
<mvc:annotation-driven />
Basically, you need check if:
Your Jackson library is existed in the project classpath
The mvc:annotation-driven is enabled
Return method annotated with #ResponseBody

How to write simple filter in Spring Securtiy MVC?

I am working on my simple REST API prototype written in Spring 3.2. I have read Spring Security documentation and many tutorials on the internet but nothing make sense to me how to secure my REST API.
My requirements are very simple - upon on value of one parameter from HTTP headers I need to allow or disallow client to consume the particular resource. I have a service that can be injected as a bean and this bean can process this task for me. What I need to know is where to place this "check" bean and how to tell to Spring to use it as a filter before the resource is consumed (I configure my application programmatically via Java class and I don't use applicationContext.xml).
I would be appreciate for some simple example - Spring configuration and filter class.
As Bart said, You can very well make use of interceptor. You can do like
#Component
public class SecurityFilter extends HandlerInterceptorAdapter{
#Override
public boolean preHandle(HttpServletRequest request,
HttpServletResponse response, Object handler) throws Exception {
/*you can do this way. set the response content type as
* 'application/json'.get the PrintWriter from response and print
* the Json object
*/
response.setContentType("application/json");
PrintWriter out = response.getWriter();
/*jsonObject can be either be a String form of json. example:
*"{ key1:'value1', key2: 'value2' }" or JSON object created
*using JSON libraries like json.org or Gson package
*/
out.print(jsonObject);
out.flush();
return false;
}
}
You have to also configure in your spring configuration file.
<mvc:interceptors>
<mvc:interceptor>
<!-- map the url path to the appropriate filter -->
<mvc:mapping path="/**" />
<bean class="com.keerthi.filter.SecurityFilter" />
</mvc:interceptor>
</mvc:interceptors>
Please read the documentation of HandlerInterceptorAdapter API. This will help you

What is the point of MultiActionController?

I came across MultiActionController today, and I'm not sure I understand what it is used for... on the Spring documentation, it says
Controller implementation that allows multiple request types to be handled by the same class. Subclasses of this class can handle several different types of request with methods of the form
On another site, they said
It aggregates multiple request handling methods into single controller, so related functionality can be kept together easily.
I'm still not understanding how is extending MultiActionController better or different than the following? Or is MultiActionController more a legacy from older versions of Spring? I feel I have some basic misunderstanding...
#Controller
public class MyController {
#RequestMapping("/SomePage.html")
public ModelAndView epdReview(
#RequestParam(value="sessionID", required=true) String sessionId,
MyFormData form,
HttpSession session,
HttpServletRequest request){
//....
}
#RequestMapping(value = "/newData.json", method = RequestMethod.POST)
public #ResponseBody ValidationResponse process(Model model,
#Valid SomeData formData, BindingResult result,
HttpSession session) {
//....
}
}
Yes, that is from the Spring 2.0 MVC API, as is anything that implements the old Controller Interface. I can't find anything around the web from a Spring Developer regarding why this one was not deprecated when all of its cousins were.
I could offer 100% pure speculation that it could be because people could have totally valid custom-implementations of the MethodNameResolver that are impossible to replace with the behaviour of DefaultAnnotationMethodHandlerAdapter. Therefore annotation based config does not provide a 100% alternative to every legitimate use of this class.
Spring offers a multi-action controller with which multiple actions can be aggregated into one controller, grouping functionality together. The multi-action controller is capable of mapping requests to method names and then invoking the right method name. Using the multi-action controller is especially handy when you have a lot of common functionality in one controller, but want to have multiple entry points to the controller
The hole point of using Annotated Controllers - like your later example- is support for request handling without depending on inheritance or framework specific classes (like four first example). In Spring Documentation you can find this:
Spring 2.5 introduces an annotation-based programming model for MVC
controllers, using annotations such as #RequestMapping, #RequestParam,
#ModelAttribute, etc. This annotation support is available for both
Servlet MVC and Portlet MVC. Controllers implemented in this style do
not have to extend specific base classes or implement specific
interfaces.
So, if you're already using Annotated Controllers there's no point in extending Spring built-in Controllers like MultiActionController.
Spring MultiActionController is used to map similar actions to single controller. So If you use MultiActionController class, you do not need to create new controller class for each action.
For example: When we login to internet banking, there is an option to add and delete payee. So we can use single PayeeController to perform similar actions such as add and delete.
Quoted from mkyong.com:
In Spring MVC application, MultiActionController is used to group related actions into a single controller, the method handler have to follow below signature :
public (ModelAndView | Map | String | void) actionName(
HttpServletRequest, HttpServletResponse [,HttpSession] [,CommandObject]);
example
package com.vitthal.common.controller;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.multiaction.MultiActionController;
public class CustomerController extends MultiActionController{
public ModelAndView add(HttpServletRequest request,
HttpServletResponse response) throws Exception {
return new ModelAndView("CustomerPage", "msg","add() method");
}
public ModelAndView delete(HttpServletRequest request,
HttpServletResponse response) throws Exception {
return new ModelAndView("CustomerPage", "msg","delete() method");
}
public ModelAndView update(HttpServletRequest request,
HttpServletResponse response) throws Exception {
return new ModelAndView("CustomerPage", "msg","update() method");
}
public ModelAndView list(HttpServletRequest request,
HttpServletResponse response) throws Exception {
return new ModelAndView("CustomerPage", "msg","list() method");
}
}
With ControllerClassNameHandlerMapping configured.
<beans ...>
<bean
class="org.springframework.web.servlet.mvc.support.ControllerClassNameHandlerMapping" />
<bean class="com.mkyong.common.controller.CustomerController" />
</beans>
Mapping Examples
Now, the requested URL will map to the method name in the following patterns :
CustomerController –> /customer/*
/customer/add.htm –> add()
/customer/delete.htm –> delete()
/customer/update.htm –> update()
/customer/list.htm –> list()
InternalPathMethodNameResolver
The InternalPathMethodNameResolver is the default MultiActionController implementation to map URL to method name. But, you are still allow to add prefix or suffix to the method name :
<beans ...>
<bean
class="org.springframework.web.servlet.mvc.support.ControllerClassNameHandlerMapping" />
<bean class="com.vitthal.common.controller.CustomerController">
<property name="methodNameResolver">
<bean class="org.springframework.web.servlet.mvc.multiaction.InternalPathMethodNameResolver">
<property name="prefix" value="test" />
<property name="suffix" value="Customer" />
</bean>
</property>
</bean>
</beans>
Now, the URL will map to the method name in the following pattern :
CustomerController –> /customer/*
/customer/add.htm –> testaddCustomer()
/customer/delete.htm –> testdeleteCustomer()
/customer/update.htm –> testupdateCustomer()
/customer/list.htm –> testlistCustomer()
Note
With annotation, the MultiActionController is more easy to configure

Spring MVC Controller: Redirect without parameters being added to my url

I'm trying to redirect without parameters being added to my URL.
#Controller
...
public class SomeController
{
...
#RequestMapping("save/")
public String doSave(...)
{
...
return "redirect:/success/";
}
#RequestMapping("success/")
public String doSuccess(...)
{
...
return "success";
}
After a redirect my url looks always something like this: .../success/?param1=xxx&param2=xxx.
Since I want my URLs to be kind of RESTful and I never need the params after a redirect, I don't want them to be added on a redirect.
Any ideas how to get rid of them?
In Spring 3.1 a preferred way to control this behaviour is to add a RedirectAttributes parameter to your method:
#RequestMapping("save/")
public String doSave(..., RedirectAttributes ra)
{
...
return "redirect:/success/";
}
It disables addition of attributes by default and allows you to control which attributes to add explicitly.
In previous versions of Spring it was more complicated.
In Spring 3.1 use option ignoreDefaultModelOnRedirect to disable automatically adding model attributes to a redirect:
<mvc:annotation-driven ignoreDefaultModelOnRedirect="true" />
Adding RedirectAttributes parameter doesn't work for me (may be because my HandlerInterceptorAdapter adds some stuff to model), but this approach does (thanks to #reallynic's comment):
#RequestMapping("save/")
public View doSave(...)
{
...
RedirectView redirect = new RedirectView("/success/");
redirect.setExposeModelAttributes(false);
return redirect;
}
In Spring 4 there is a way to do this with java config, using annotations. I'm sharing it in case anyone needs it as I needed it.
On the config class that extends WebMvcConfigurerAdapter, you need to add:
#Autowired
private RequestMappingHandlerAdapter requestMappingHandlerAdapter;
#PostConstruct
public void init() {
requestMappingHandlerAdapter.setIgnoreDefaultModelOnRedirect(true);
}
With this, you do not need to use RedirectAttributes, and it is an equivalent in java config to Matroskin's answer.
If you're using Spring 3.1, you can use Flash Scope,
otherwise you can take a look at the method used in the most voted (not accepted) answer here:
Spring MVC Controller redirect using URL parameters instead of in response
EDIT:
Nice article for 3.1 users:
http://www.tikalk.com/java/redirectattributes-new-feature-spring-mvc-31
Workaround for non-3.1 users:
Spring MVC custom scope bean
Try this:
public ModelAndView getRequest(HttpServletRequest req, Locale locale, Model model) {
***model.asMap().clear();*** // This clear parameters in url
final ModelAndView mav = new ModelAndView("redirect:/test");
return mav;
}

Java - Spring MVC - Automatically populate object from form submission?

In ASP.NET MVC in the controller I can just have an object from my model be a parameter in one of my methods, and a form submission that gets handled by that method would automatically populate the object.
eg:
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Edit(User u){...}
The user object will automatically be populated for be from the form submission.
Is there a way to have this automatically happen using Spring MVC, and if so how do I do it?
In Spring MVC (with Spring MVC 2.5+ annotation-based configuration) it looks exactly the same way:
#RequestMapping(method = RequestMethod.POST)
public ModelAndView edit(User u) { ... }
The User object will be automatically populated. You may also explicitly specify the name of the corresponding model attribute with #ModelAttribute annotation (by default attribute name is a argument's class name with first letter decapitalized, i.e. "user")
... (#ModelAttrbiute("u") User u) ...
http://static.springsource.org/spring/docs/2.0.x/api/org/springframework/web/portlet/mvc/SimpleFormController.html#onSubmitAction(java.lang.Object)
Create a Form Controller, for example PriceIncreaseFormController and make it extend SimpleFormController
override the method public ModelAndView onSubmit(Object command)
there are many variants of the above. look for the right method that suits your need. For simple flow the above method should be sufficient.
Inside the method, you can typecast command and get your Command class.
commandObj = ((PriceIncrease) command)
commandObj will have the parameters populated by spring.
in your springapp-servlet.xml you should tell spring about the PriceIncrease command class as follows and also you should have a POJO for your command class created.
<bean name="/priceincrease.htm" class="springapp.web.PriceIncreaseFormController">
<property name="commandClass" value="springapp.service.PriceIncrease"/>
....
In Servlets no, but in Spring MVC absolutely. Take a look at the web framework docs.
Specifically Section 13.11.4, 9th bullet point.

Categories