I'm trying to achieve so that Thymeleaf can work together with Spring MVC 3 and use 2 view resolvers, one for jsp and one for html templates. I'd like my Thymeleaf ServletContextTemplateResolver to be asked first to attempt to resolve a view and if it can't find one, pass on to the Spring MVC 3 InternalResourceViewResolver.
I've set the order value of ServletContextTemplateResolver to 1 this way:
<bean id="templateResolver"
class="org.thymeleaf.templateresolver.ServletContextTemplateResolver">
<property name="prefix" value="/WEB-INF/views/" />
<property name="suffix" value=".html" />
<property name="templateMode" value="HTML5" />
<property name="order" value="1" />
<property name="cacheable" value="false" />
</bean>
and the order of InternalResourceViewResolver" to 2 in the same fashion:
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/views/" />
<property name="suffix" value=".jsp" />
<property name="order" value="2" />
</bean>
As I understand it from the docs the highest order is consulted last.
In the "views" folder I have one "index.jsp" and one "index.html" and my general idea is that first ServletContextTemplateResolver will be asked to attempt resolving and it will resolve to "index.html" if there is one, and only if no suitable view can be found by ServletContextTemplateResolver will the InternalResourceViewResolver be asked to resolve the view.
But the result I have is that when InternalResourceViewResolver is active, it resolves all views no matter what. If I comment it out then ServletContextTemplateResolver resolves fine.
Are these resolvers impossible to pair up in this fashion? What's the alternative?
Thymeleaf throws an error when trying to find pages outside of their view resolver instead of passing it onto the next view resolver. By setting the excludeViewNames, skips trying to resolve the view name within Thymeleaf. See my example code below.
/**
* Configures a {#link ThymeleafViewResolver}
*
* #return the configured {#code ThymeleafViewResolver}
*/
#Bean
public ThymeleafViewResolver thymeleafAjaxViewResolver()
{
String[] excludedViews = new String[]{
"login", "logout"};
AjaxThymeleafViewResolver resolver = new AjaxThymeleafViewResolver();
resolver.setTemplateEngine(templateEngine());
resolver.setOrder(1);
/*
* This is how we get around Thymeleaf view resolvers throwing an error instead of returning
* of null and allowing the next view resolver in the {#see
* DispatcherServlet#resolveViewName(String, Map<String, Object>, Locale,
* HttpServletRequest)} to resolve the view.
*/
resolver.setExcludedViewNames(excludedViews);
return resolver;
}
Related
This is an existing monolith app and fix is required without a drastic change of the setup.
Project setup:
project 1 (config) - > where all mq-xml files are present (e.g - ibm_mq_config.xml)
e.g - content of dev_bm_mq.xml
${hname}
${port}
${qmgr}
1
<!-- JMS Queue Connection Factory -->
<bean id="jmsQueueIdsConnectionFactory"
class="org.springframework.jms.connection.SingleConnectionFactory">
<property name="targetConnectionFactory">
<ref bean="mqIdsConnectionFactory" />
</property>
</bean>
<!-- JMS Destination Resolver -->
<bean id="jmsDestinationResolver"
class="org.springframework.jms.support.destination.DynamicDestinationResolver">
</bean>
<!-- JMS Queue Template -->
<bean id="jmsQueueIdsTemplate" class="org.springframework.jms.core.JmsTemplate">
<property name="connectionFactory">
<ref bean="jmsQueueIdsConnectionFactory" />
</property>
<property name="defaultDestinationName">
<value>${myQUEUE}</value>
</property>
<property name="pubSubDomain">
<value>false</value>
</property>
<property name="receiveTimeout">
<value>20000</value>
</property>
</bean>
<bean id="jmsContainer"
class="org.springframework.jms.listener.DefaultMessageListenerContainer">
<property name="connectionFactory" ref="jmsQueueConnectionFactory" />
<property name="destinationName">
<value>${myQUEUE}</value>
</property>
<property name="messageListener" ref="simpleMessageListener" />
<property name="concurrentConsumers" value="2" />
<property name="maxConcurrentConsumers" value="3" />
<property name="idleTaskExecutionLimit" value="4" />
<property name="maxMessagesPerTask" value="4" />
<property name="receiveTimeout" value="5000" />
<property name="recoveryInterval" value="5000" />
<property name="sessionTransacted" value="true" />
</bean>
****Project B (App)****
loads the spring xml from project config as below:
WebContent/WEB-INF/spring/sprint-context.xm
<import resource="classpath*:com/my/package/${config.env}-${config-broker}.mq.xml"
public class TestMessageListener implements MessageListener {
public void onMessage(Message message) {
//process the message
}
}
When the server starts up, it's able to start the server and setup the listener without any issues.
Issue with the above setup : When we scale the app horizontally (add few nodes ), it's gives max channel issues which I am trying to solve.
Requirement:
based on a DB table I want to turn off the mq listener on few nodes on the fly. or when I horizontally scale the app.
e.g -
Table:mq-config
|host|broker|flag
-----------------------------
|qa5|ibm|false
|qa2|ibm|true
So, I want mq listener on qa5 not to start and qa2 to start and listen to the Queue. Also, I want to stop/start listener on the fly (just by updating the DB)
Question - Any thoughts on how do I achieve the above use case without re-writing the entire setup.
Inject the listener container (e.g. #Autowired).
Then
jmsContainer.stop();
jmsContainer.shutdown();
...
jmsContainer.initialize();
jmsContainer.start();
You can also set the autoStartup property to false to prevent the container from starting during application initialization (but don't call initialize() before the first start() - only after calling shutdown().
SpringMVC can't request html
I define a
#RequestMapping(value = {"/","/index"}).
I can't request index.html:
try adding "/index.html" to the #RequestMapping.
If you are trying to display the 001.html by going to /index, then make sure your 001.html is in the folder your view resolver is looking at
The value of #RequestMapping is not your view name, it's url path.
View name is defined in return.Try return index.html.
If you defined this in spring-servlet.xml:
<bean id="viewResolver"
class="org.springframework.web.servlet.view.UrlBasedViewResolver">
<property name="viewClass"
value="org.springframework.web.servlet.view.JstlView" />
<property name="prefix" value="/" />
<property name="suffix" value=".html" />
</bean>
You need return index.
How can I config IOC basing condition,like following:
<bean id="beanid" class="com...Class1" >
<if var='xxx'>
<property name="formView"
value="RegistrationApprovalForm" />
<else if var ='yyy'>
<property name="formView"
value="RegistrationApprovalForm1" />
</bean>
so I can put var in properties files,this will make configration easy.
Here is the code.
${ServiceMgmt.showEnabler}
</bean>
I want to redirect to the view based on configuration as below.
else
Is this possible with spring configuration??
I;m trying to create RSS feeds for my web site. I follow the tutorial from mkyong (http://www.mkyong.com/spring-mvc/spring-3-mvc-and-rss-feed-example/) which was quite useful. According to this tutorial i create a model class and the following class
public class CustomRssViewer extends AbstractRssFeedView{
#Override
protected void buildFeedMetadata(){
//some code
}
#Override
protected List<Item> buildFeedItems(){
//some code
}
}
And finally the controller class
#Controller
public class RssController {
#RequestMapping(value="/rssfeed", method = RequestMethod.GET)
public ModelAndView getFeedInRss() {
//set the RSS content
ModelAndView mav = new ModelAndView();
mav.setViewName("rssViewer");
mav.addObject("feedContent", items);
return mav;
}
}
According to the tutorial the View rssViewer belongs the class CustomRssViewer , so i need to write it at the dispatcher servlet the following lines of code:
<bean class="org.springframework.web.servlet.view.BeanNameViewResolver" />
<bean id="rssViewer" class="com.mkyong.common.rss.CustomRssViewer" />
My problem is that i'm using apache tiles. So the rssViewer can not be recognised as i didn't enhanced it to the tiles definition. And i really don't know how can i do this. For example i need to write something as the following:
<definition name="rssViewer" template="?">
<put-attribute name="title" value=""/>
<put-attribute name="content" value=""/>
</definition>
At the template i don't know what to declare as well as at the put-attribute.Because until now at the template i use to declare the direction that a specific jsp exists. Something like this:
template="/WEB-INF/pages/mypage.jsp"
And also at the view-properties i don't know what should i declare.
Thanks in advance for any comment or response.
You should use a ContentNegotiatingViewResolver in conjuction with that example's BeanNameViewResolver. Just declare the order property of your already existing BeanNameViewResolver to be 1, and set the order property of the new ContentNegotiatingViewResolver to 0.
You should then configure the ContentNegotiatingViewResolver to use the appropriate View for RSS, and set the media type for RSS.
Here is an example from the Spring Docs:
<bean class="org.springframework.web.servlet.view.ContentNegotiatingViewResolver">
<property name="mediaTypes">
<map>
<entry key="atom" value="application/atom+xml"/>
<entry key="html" value="text/html"/>
<entry key="json" value="application/json"/>
</map>
</property>
<property name="viewResolvers">
<list>
<bean class="org.springframework.web.servlet.view.BeanNameViewResolver"/>
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/jsp/"/>
<property name="suffix" value=".jsp"/>
</bean>
</list>
</property>
<property name="defaultViews">
<list>
<bean class="org.springframework.web.servlet.view.json.MappingJacksonJsonView" />
</list>
</property>
</bean>
Note, they are using atom, not RSS, but the idea is the same. Also they do not set the order (which you should do).
Is there some annotation in SpringMVC 3.1 to turn off browser caching on an MVC controller method?
#Controller
#RequestMapping("/status")
public class StatusController {
#RequestMapping(method=RequestMethod.GET)
//anyway to have an annotation here that turns of all the http caching headers?
public String get()
{
// do some work here
return "status";
}
}
As far as I can tell there isn't an annotation, but there is a way to configure it via XML using an interceptor. For example:
<mvc:interceptors>
<mvc:interceptor>
<mvc:mapping path="/status"/>
<bean id="noCacheWebContentInterceptor"
class="com.nyx.spring.mvc.WebContentInterceptor">
<property name="cacheSeconds" value="0"/>
<property name="useExpiresHeader" value="true"/>
<property name="useCacheControlHeader" value="true"/>
<property name="useCacheControlNoStore" value="true"/>
</bean>
</mvc:interceptor>
</mvc:interceptors>