Multiple View Rendering issue in Spring Boot - spring

I am using Spring Boot application. In that i have used Spring MVC at front end. I have a requirement to download various reports like pdf, xls. As i understand, Spring Boot, internally uses ContentNegotiatingViewResolver, BeanNameViewResolver, ViewResolverComposite and InternalResourceViewResolver. I am not overriding any beans in code and using default configurations as provided
Currently to test, i am using below url
http://localhost:8080/SearchCustomers.xls
Properties in application.properties file are
spring.mvc.media-types.pdf=application/pdf
spring.mvc.media-types.xls=application/vnd.ms-excel
In my code, i have created a view class which extends from AbstractPdfView.It is a spring bean and it's id is "SearchCustomers".Controller code returns "SearchCustomers" as a view name.
Whenever i execute above code, ContentNegotiatingViewResolver doesn't returns any view.ContentNegotiatingViewResolver internally uses BeanNameViewResolver, ViewResolverComposite and InteralResourceViewRsolver to resolve view names.In our case, the bean name matches with view but its media type doesn't as it matches the path extension internally along with the bean content type.This is a correct Behavior?
However DispatcherServlet reiterates through all view resolvers and which is causing an issue.
In the second iteration, BeanNameViewResolver matches the bean id with returned view name from controller and it invokes the pdf view,which i believe is incorrect.
Is there any workaround for this?

I found out the solution
If you want just one controller method to handle all type of requests..then in that case your view should be given id in below format
id - viewname + path extension
Ex
My controller method returns view name as "SearchCustomers" for all type of request..
I have created different views for different requests like
#Component("SearchCustomers.pdf")
class MyPdfView extends from AbstractPdfView
#Component("SearchCustomer.xls")
class MyExcelView extends from AbstractExcelView
Interanally, CNVR searches for these beans. and then it matches the mediatype/contenttype which returns the correct view

Related

Spring Controller Url

I have question about controllers. Always when i working with controller im start to declare #RequestMapping for example if have UserController then is #RequestMapping("/user");
What if i want to declare another path in this same controller? For example im have #GetMapping("/info") and i will get info about user, but what if i want to declare on this same controller path localhost:8080/topic/blablabla? Is another solution than delete #RequestMapping from controller and make on every Get/PostMapping another path?
Defining a #RequestMapping at the controller level; it means narrowing it down to your criteria.
You can use the #RequestMapping annotation to map requests to controllers methods. It has various attributes to match by URL, HTTP method, request parameters, headers, and media types. You can use it at the class level to express shared mappings or at the method level to narrow down to a specific endpoint mapping. Read More
It is good you want to do, sometimes I need it too but as far as I research it is not supported now.

Mapping url to a single controller with different method with Spring 3

I have to map different url to single controller
e.g.
/test/read
/test1/read
/test2/read
/test/submit
/test1/submit
/test2/submit
So at the class level I use #RequestMapping(values ={"/test/*", "/test1/*","/test2/*"}) and at method level #RequestMapping(read) and for other method #RequestMapping("submit").
This fails and says that read is already mapped.
By default I think RequestMappingHandlerMapping is being used.
How to do this kind of mapping please suggest.

Practical use of ApplicationContextAware in spring

I have had chance of working on only one project using spring , and the way it worked was
Make a singleton class (lets say MySpringHelper), that has method like getBean(String beanName)
What getBean(String) does is, it first checks existence of applicationContext, if it exists uses same to get the bean , else creates new applicationContext and returns the bean
Wherever in you project you need a bean simply call MySpringHelper.getBean("abc")
Keeping this in mind , when i was studying spring , i noticed interface "ApplicationContextAware" ... I am not sure when will this be needed, uses above pattern such interface seems not of any use. Or the above Singleton MySpringHelper pattern/approach is incorrect ??
Looking forward to learn from your experience
To give more details on application , its like a pdf file generator, 1 pdf file having 12-15 different charts, so the main method runs 1 thread for each chart , and inside these chart logic we are using singleton MySpringHelper
Why are you checking the existance of applicationContext? It should be there if your helper bean is configured in xml and has setter method in it. There is no need to create application context in that case.
For your case, I would suggest you get applicationContext injected by Spring rather than by using ApplicationContextAware.

Accessing Spring Controller Name from View

With Spring, how can i retrieve the following Controller attributes in the view?
Controller name
Controller's #RequestMapping URI
Action method name
Action method's #RequestMapping URI
One approach which i have tried is by creating a subclass of HandlerInterceptorAdapter and overriding postHandle. I register my subclass as an mvc:interceptor for a list of given paths - which is clunky to maintain but was the only way to avoid my interceptor being called for ResourceHandler requests (which i don't want). In my postHandle i can easily add the 2 name attributes, but not the URIs...
Parsing from the HttpRequest object requires constraints on all Controller RequestMappings. I.e. i must always map /Controller/Action or equiv scheme. Quite limiting.
Creating an ApplicationContext and querying that with the requestURI is too long-winded.
I am thinking about dropping the HandlerInterceptorAdapter and instead defining a BaseController for all my controllers to extend.
I wanted to ask before i do this, is there a better approach?
You haven't stated why you need to do this (it sometimes helps to include your motivation, as others can suggest alternative approaches).
But I'm guessing that the Spring 3.1 features loosely termed "end point documentation" may do what you are asking... See RequestMappingHandlerMapping in the Spring documentation which doesn't provide a lot of detail, so this example project is the best place to see it in action:
Spring MVC 3.1 Demo App
example controller
example JSP page

Displaying Data Table And Submiting Form In One Page Struts

I'm new in Struts, currently I'm using struts 1.3 to build simple Contact application
I want to display data table contains contact list from the database, in the same page I want to create a form for creating new contact and then insert it to database.
I'm using Spring bean and hibernate to do database operation and logic. So here is my flow, my action class will call spring bean, and the spring bean will call dao classes for database operation do some logic, then my action class will put the list into request object named contactList, then in jsp file I'm iterate it using logicLiterate tag.
Displaying the table and submiting all works fine, but when I do validating in ActionForm, and I want to display the error message, I have an error 500. This is because the jsp cannot find attribute named contactList in the request object, because if there is an error in ActionForm classes, Struts not calling the method at my Action class that will read the database and put it into the request object. I can try calling the spring bean in my ActionForm, but I'm afraid it not appropriate, because if there is no error then I will call the spring bean twice for the same work. What do you suggest me to do?
My bad not to read the doc carefully, now i understand that action tag in struts-config.xml have "input" attribute, this attribute specifies the physical page to which the request has to be forwarded if there is an error.
In my case, i just have to specified the input attribute to current path (eg. /contacts.do, etc) so the Action class can do its Action method.
Please note that, this request is forward requuest, not redirect.

Resources