Mapping Multiple Controllers in Spring MVC - spring-mvc

Define two controllers user and data as follows:
// 1st Controller
#Controller
#RequestMapping(value = {"/", "user"})
public class UserLoginController {
#Autowired
private UserLoginService userLoginService;
#RequestMapping(value = "/", method = RequestMethod.GET)
public String showLoginForm(#ModelAttribute UserLogin userLogin) {
//model.addAttribute(new UserLogin());
//System.out.println("showLoginForm() is called");
return "loginForm";
}
}
//Second COntroller
#Controller
#RequestMapping(value = "user/data/")
public class WorkplanController {
#Autowired
private WorkplanService WorkplanService;
#RequestMapping(value = "importForm", method = RequestMethod.GET)
public ModelAndView importForm(#ModelAttribute SheetUpload sheetUpload){
return new ModelAndView("uploadWorkplan");
}
#RequestMapping(value= "doUpload", method = RequestMethod.POST)
public ModelAndView doUpload(#RequestParam CommonsMultipartFile[] uploadFile, SheetUpload fileUpload, Workplan workplan, HttpServletRequest request) {
return new ModelAndView("uploadSucess");
}
}
When i make request to the doUpload(), it shows HTTP Status 400 Error.
My question is two-fold:
1. Why do have i have to include the user like this: #RequestMapping(value = "user/data/") to make request to the 2nd controller why not like this #RequestMapping(value = "data/")?
2. What do i need to change to make a successful call to the 2nd method in the second controller?
Here is the form am trying to submit:
<form:form action="doUpload" modelAttribute="sheetUpload" method="post"
enctype="multipart/form-data">
<form:select class="createusers_select_menu" path="From">
<form:option value="">Select...</form:option>
<form:option value="A">A</form:option>
<form:option value="B">B</form:option>
<form:option value="C">C</form:option>
</form:select>
<form:input class="browse_btn" path="uploadFile" type="file" />
<input type="submit" class="selct_workplan_2_btn" name="" value=" "/>
</form:form>

Why do have i have to include the user like this: #RequestMapping(value = "user/data/") to make request to the 2nd controller why not like this #RequestMapping(value = "data/")?
You don't have to. Change it to #RequestMapping(value="/data")
What do i need to change to make a successful call to the 2nd method in the second controller?
Try to get it working with a single file field only, then report back. There are lots of tutorials on the web to show how to upload files with Spring.

Related

Getting null values in Spring MVC controller when submitting data from the jsp

I have a jsp form with an input box, a domain object with get/set methods, and a controller. When I submit the form I get null values in the controller. The "set" method is never being called in the domain object when i submit the form but the object itself is being called.
Order.jsp
<portlet:defineObjects />
<portlet:actionURL portletMode="view" var="createNewOrderURL">
<portlet:param name="action" value="createNewOrder" />
</portlet:actionURL>
<div>
<form:form name="form" method="post" commandName="refOrder" action="${createNewOrderURL}" id="createOrder">
TestName : ${refOrder.name}<br/> <!-- here I get the correct value to display -->
<form:input path="referenceNum" />
<input type="submit" value="Submit" />
</form:form>
</div>
Order.java
public class Order {
private String name = "Name1";
private String referenceNum;
public Order(){
System.out.println("Inside Order.java");
System.out.println(getReferenceNum());
}
public Order(String name, String referenceNum) {
this.name = name;
this.referenceNum = referenceNum;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getReferenceNum() {
return referenceNum;
}
public void setReferenceNum(String referenceNum) {
this.referenceNum = referenceNum;
}
SalesOrderController.java
#RenderMapping
public String defaultRender(RenderRequest request, RenderResponse response, Model model) throws SQLException, NamingException{
model.addAttribute("refOrder",new Order());
return "SalesOrderEntry";
}
#ActionMapping(params={"action=createNewOrder"})
public void addNewOrder(ActionRequest request, ActionResponse response, #ModelAttribute("refOrder") Order order)throws NamingException, SQLException{
System.out.println("Inside addNewOrder method");
System.out.println("New Order is --> "+order.toString());
System.out.println("RefNum - "+order.getReferenceNum());
System.out.println("request.getParameter is "+request.getParameter("referenceNum"));
}
I get null for all the print statements in the controller. Have been trying to fix this for two days now and I can't find what's wrong. Would really appreciate if someone can help me get this to work.
Do you have the following in your src/main/webapp/WEB-INF/liferay-portlet.xml descriptor?
<requires-namespaced-parameters>false</requires-namespaced-parameters>
Also, you might want to take a look at the PortletMVC4Spring project, which is the successor to Spring Portlet MVC. The GitHub project contains archetypes that work in Apache Pluto and Liferay Portal. The requires-namespaced-parameters config option is conveniently set in the archetypes.

Need to pass object from one controller to another controller

I am having 2 controllers in my class :-1st controller return to a jsp page , in that jsp i am using a form ,on submitting that form it calls 2nd controller . I want to pass one object from 1st controller to 2nd controller and dont want to send that object to intermediate jsp page so is there any way to do this .I dont want to use session attribute also
this is my 1st controller
#RequestMapping(value = "/login", method = RequestMethod.GET)
public static String login(final Model model) {
final Studentdata studentdata = new Studentdata();
studentdata.setName("username");
return "Login" ;
}
this is my Login.Jsp
<form action="/loungeHotel/checkLogin" method="post">
<input type="submit" value="submit">
</form>
this is 2nd controller
#RequestMapping(value = "/checkLogin", method = RequestMethod.POST)
public static String checkLogin(final Model model) {
System.out.println("here i want to access studentdata");
return "MyAccount";
}
I think HttpSession is the right choice.
If you don't want to use HttpSession or any server storage such as Database, ... You can use this way - Client storage by using hidden inputs
Modify login to store studentdata in request attribute
#RequestMapping(value = "/login", method = RequestMethod.GET)
public static String login(HttpServletRequest request, final Model model) {
final Studentdata studentdata = new Studentdata();
studentdata.setName("username");
request.setAttribute("studentData", studentdata);
return "Login" ;
}
Modify login jsp
<form action="/loungeHotel/checkLogin" method="post">
<!-- Write all studentdata Properties as Hidden inputs -->
<input type="hidden" name="property1" value="${studentData.property1}"
<input type="hidden" name="property2" value="${studentData.property2}"
<input type="hidden" name="property3" value="${studentData.property3}"
<input type="submit" value="submit">
</form>
Modify checkLogin
RequestMapping(value = "/checkLogin", method = RequestMethod.POST)
public static String checkLogin(HttpServletRequest request, final Model model) {
System.out.println("here i want to access studentdata");
// Recreate StudentData From request.getParameter(...)
Studentdata studentdata = new Studentdata();
studentdata.setProperty1 ( request.getParameter("property1"));
// ... You may have to convert data too
return "MyAccount";
}

Spring mvc form:select path is custom map in model attribute

How to bind a map property of the model and send the selected value back to the controller?
i am able to populate the drop down but on submitting the form getting error 400 - bad request.
MyModel.java:
public class MyModel{
private Map<MySubModel, String> subModel = new HashMap<MySubModel, String>();
private SubModel subModelSearched;
}
SubModel.java:
public class SubModel{
public String id;
public String name;
}
JSP:
<form:form action="/mySearch" modelAttribute="myModel" method="post">
<form:select path="subModelSearched">
<form:options items="${myModel.subModel}/>
</form:select>
.....
</form:form>

Configure multiple controllers in Spring MVC, and call one controller's method from another controller

I am trying to configure multiple controller in my application and also trying to redirect from one controller to other.
Error:
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping#0': Invocation of init method failed; nested exception is java.lang.IllegalStateException: Ambiguous mapping found. Cannot map 'nc' bean method.
EDIT :
First Controller
#Controller
#RequestMapping(value = "/nc")
public class StockController {
#RequestMapping(value = "/testMap", method = RequestMethod.GET)
public String redirectToStockList(#RequestParam(value = "testInput") String testInput) {
System.out.println("In StockController..!!");
return "SampleTamplate";
}
}
Second Controller
#Controller
public class WelcomeController {
#Autowired
private UsersServiceImpl serviceImpl;
private String redirectedURL;
private static final Logger logger = LoggerFactory
.getLogger(WelcomeController.class);
#RequestMapping(value = { "/", "/login" }, method = RequestMethod.GET)
public String login(#RequestParam(value = "username") String username) {
logger.debug("In login() method.");
System.out.println("In WelcomeController..!!");
return "Login";
}
}
jsp:
First Form:
<form action="testMap" method="post">
<input type="text" class="form-control" name="testInput"/>
</form>
Second Form:
<form action="login" method="post">
<input type="text" class="form-control" name="username"/>
</form>
When I submit both forms one by one, control goes to 'WelcomeController' every time. And for first form, It gives 'resources not found' error that's OK because there is no mapping present as "/testMap" in welcome controller.
So what I want is, to call specific controller on my form submission and also call one controller's method from another controller.
Any help would be appreciated.
I will try to answer this question in both Grails and Spring way as this is the best time to introduce Grails here.
In spring when call is leaving from controller then RequestDispatcher actually helps to catch the call or to check the exact view resolver. Now, as you want to transfer call to another controller here sping provides API (http://docs.spring.io/spring/docs/3.0.x/spring-framework-reference/htmlsingle/spring-framework-reference.html#mvc-redirecting) Inshort you have to use view name like "forward:controllerName" like
#RequestMapping({"/someurl"})
public String execute(Model model) {
if (someCondition) {
return "forward:/someUrlA";
} else {
return "forward:/someUrlB";
}
In grails there is forward method you can find in controller API which does things for you (http://grails.github.io/grails-doc/2.0.4/api/org/codehaus/groovy/grails/plugins/web/api/ControllersApi.html). It actually passes the same session to next requested controller.
Request you to please try to use it. Hope this help.
In the below example the LoginController redirects to the /menu URL if there are validation errors upon submitting a login form by calling the menuMapping() method that resides within the MenuController class.
(NOTE: I have included the use of the BindingResult class and a hypothetical form as this would be a valid reason for wanting to redirect to another controller. However, below solution would still work as well without the BindingResult and if statement without the use of a form).
#Controller
public class LoginController {
MenuController menuController;
#RequestMapping(value = "/login")
public String loginMapping(BindingResult result){
if(result.hasErrors) {
return "login";
}
else {
return menuController.menuMapping();
}
}
With your MenuController in another class like so:
#Controller
public class MenuController {
#RequestMapping(value = "/menu")
public String menuMapping(){
return "menu";
}
}
(EDIT: if you wanted to apply the redirect and the controller methods were within the same class then the loginMapping return statement would simply be return menuMapping(); rather than return menuController.menuMapping();

Spring3 MVC - how to impliment CRUD correctly on the same controller?

I am trying to create simple CRUD controller and view using Spring mvc.
I am able to:
Get the document list
Upload document
Deleted Document
If I would like to send the request using FORM,
How do i implement Download Document?
Should I use for every document?
Another thing - am i using the MVC framework correctly?
<html>
<body>
<!-- the list: -->
<c:forEach items="${documentList}" var="documentRow">
<Generate table here>
<!-- upload part -->
<form:form modelAttribute="uploadDocument" method="post" enctype="multipart/form-data">
<form:input path="fileData" type="file"/>
<input type="hidden" id="actUploadocument" name="action" value="uploadDocument" />
</form:form>
<!-- delete part -->
<form:form method="post" enctype="multipart/form-data">
<input type="hidden" id="documentId" value="" />
<input type="hidden" id="actUploadocument" name="action" value="deleteDocument" />
</form:form>
</body>
</html>
The CRUD controller?
#Controller
#RequestMapping("/documents")
public class DocumentsController
{
#Autowired
private MainService mainService;
#RequestMapping(method = RequestMethod.GET)
public String listDocuments(Model model) {
List<Document> docs = mainService.getAllDocuments();
model.addAttribute("documentList",docs);
model.addAttribute(new UploadDocument());
return "admin/documents";
}
#RequestMapping(method = RequestMethod.POST , params="action=uploadDocument")
public String uploadDocument(UploadDocument uploadDocument){
savedocument(uploadDocument);
return "redirect:/admin/documents.do";
}
#RequestMapping(method = RequestMethod.POST , params="action=removeDocument")
public String removeDocument(#RequestParam(value="documentId", required=true) String documentId){
savedocument(documentId);
return "redirect:/admin/documents.do";
}
#RequestMapping(method = RequestMethod.POST , params="action=downloadDocument")
public String downloadDocument(#RequestParam(value="documentId", required=true) String documentId,
HttpServletRequest request,HttpServletResponse response ) {
writeDocToResponse(documentId,response);
return null;
}
Basically all you need to open file download dialog is a set response properties to identify HTTPresponce as attachment.
For instance:
response.reset();
response.setContentType(getYourFileContentType());
response.setHeader("Content-Disposition","attachment; filename=\""+getYourFileName()+"\"");
Then you may call your service method to stream file.

Resources