sec:authorize doesn't work - spring-mvc

Recently I have started a new project and decided to use the latest versions of spring, spring security and thymeleaf
I have included these packets
def springVersion = '4.1.6.RELEASE'
def securityVersion = '4.0.1.RELEASE'
def thymeleafVersion = '2.1.2.RELEASE'
compile "org.springframework:spring-core:$springVersion"
compile "org.springframework:spring-webmvc:$springVersion"
compile "org.springframework.security:spring-security-web:$securityVersion"
compile "org.springframework.security:spring-security-config:$securityVersion"
compile "org.thymeleaf:thymeleaf-spring4:$thymeleafVersion"
compile "org.thymeleaf.extras:thymeleaf-extras-springsecurity4:$thymeleafVersion"
I have added #EnableWebSecurity and #Bean SpringSecurityDialect to my configuration.
In the layout.html I have
<ul class="nav navbar-nav navbar-right">
<li sec:authorize="isAnonymous()"><a th:href="#{/login}">Login</a></li>
<li sec:authorize="isAuthenticated()"><a th:href="#{/logout}">Logout</a></li>
</ul>
<br>
Neither of the options show up. Moreover, when I replace those calls with true that doesn't change anything. And I don't see any error messages when make an error in function name like isAnon().
Am I missing something?
UPD
Security config
#Configuration
#EnableWebSecurity
#EnableGlobalMethodSecurity(prePostEnabled=true)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
#Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication().withUser("admin").password("admin").roles("ADMIN");
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.csrf().disable()
.formLogin()
.loginPage("/login")
.failureUrl("/login-error")
.and()
.logout()
.logoutSuccessUrl("/")
.logoutRequestMatcher(new AntPathRequestMatcher("/logout"));
}
}
Web config
#Configuration
#EnableWebMvc
#ComponentScan(basePackages = {"stats.web.controller","stats.web.domain","stats.mapper", "stats.core.service;"})
#Import({ WebSecurityConfig.class })
public class WebConfig extends WebMvcConfigurerAdapter {
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/resources/**").addResourceLocations("/resources/");
}
#Override
public void addInterceptors(InterceptorRegistry registry) {
LocaleChangeInterceptor localeChangeInterceptor = new LocaleChangeInterceptor();
localeChangeInterceptor.setParamName("lang");
registry.addInterceptor(localeChangeInterceptor);
}
#Bean
public LocaleResolver localeResolver() {
CookieLocaleResolver cookieLocaleResolver = new CookieLocaleResolver();
cookieLocaleResolver.setDefaultLocale(StringUtils.parseLocaleString("en"));
return cookieLocaleResolver;
}
#Bean
public ServletContextTemplateResolver templateResolver() {
ServletContextTemplateResolver resolver = new ServletContextTemplateResolver();
resolver.setPrefix("/WEB-INF/views/");
resolver.setSuffix(".html");
resolver.setTemplateMode("HTML5");
resolver.setCacheable(false);
resolver.setCharacterEncoding("UTF-8");
return resolver;
}
public SpringTemplateEngine templateEngine() {
SpringTemplateEngine engine = new SpringTemplateEngine();
engine.addDialect(securityDialect());
engine.setTemplateResolver(templateResolver());
return engine;
}
#Bean
public SpringSecurityDialect securityDialect() {
return new SpringSecurityDialect();
}
#Bean
public ViewResolver viewResolver() {
ThymeleafViewResolver viewResolver = new ThymeleafViewResolver();
viewResolver.setTemplateEngine(templateEngine());
viewResolver.setOrder(1);
viewResolver.setViewNames(new String[]{"*"});
viewResolver.setCache(false);
viewResolver.setCharacterEncoding("UTF-8");
return viewResolver;
}
#Bean
public MessageSource messageSource() {
ReloadableResourceBundleMessageSource messageSource = new ReloadableResourceBundleMessageSource();
messageSource.setBasenames("classpath:messages/messages", "classpath:messages/validation");
messageSource.setUseCodeAsDefaultMessage(true);
messageSource.setDefaultEncoding("UTF-8");
messageSource.setCacheSeconds(0);
return messageSource;
}
}
Not sure what bootstrap classes are needed, but I've inspected the page, the second ul that supposed to have login link is empty:
<ul class="nav navbar-nav">
::before
<li>...</li>
<li>...</li>
<li>...</li>
::after
</ul>
<ul class="nav navbar-nav navbar-right">
::before
::after
</ul>

Here is the XML config as I said. Kindly remove the files which you have, annotate your methods to #Service, #Repository for DAO, #Controller for Controller and #Entity for model. PLease dont forget #Transactional. I am authenticating against a DB in postgreSQL, but you can change the dialect.
web.xml :
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/javaee"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" version="3.0"
>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/spring/root-context.xml,/WEB-INF/spring/appServlet/security-applicationContext.xml</param-value>
</context-param>
<session-config>
<session-timeout>1440</session-timeout>
</session-config>
<listener>
<listener-class>org.springframework.web.context.request.RequestContextListener</listener-class>
</listener>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<filter>
<filter-name>springSecurityFilterChain</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
<async-supported>true</async-supported>
<init-param>
<param-name>contextAttribute</param-name>
<param-value>org.springframework.web.context.WebApplicationContext.ROOT</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>springSecurityFilterChain</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<servlet>
<servlet-name>403Jsp</servlet-name>
<jsp-file>/WEB-INF/views/error/403.jsp</jsp-file>
</servlet>
<servlet-mapping>
<servlet-name>403Jsp</servlet-name>
<url-pattern>/403</url-pattern>
</servlet-mapping>
<listener>
<listener-class>org.springframework.security.web.session.HttpSessionEventPublisher</listener-class>
</listener>
<servlet>
<servlet-name>appServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/spring/appServlet/servlet-context.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
<async-supported>true</async-supported>
</servlet>
<servlet-mapping>
<servlet-name>appServlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>default</servlet-name>
<url-pattern>*.png</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>default</servlet-name>
<url-pattern>*.jpg</url-pattern>
</servlet-mapping>
<filter>
<filter-name>encodingFilter</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
<init-param>
<param-name>forceEncoding</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>encodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
</web-app>
Servlet-context.xml :
<security:global-method-security
secured-annotations="enabled"
jsr250-annotations="disabled"
pre-post-annotations="enabled"/>
<context:component-scan base-package="com.journaldev.spring" use-default-filters="false">
<context:include-filter type="annotation" expression="org.springframework.stereotype.Controller" />
</context:component-scan>
<context:property-placeholder location="classpath:application.properties"/>
<mvc:annotation-driven>
<mvc:argument-resolvers>
<beans:bean class="org.springframework.mobile.device.DeviceWebArgumentResolver"/>
</mvc:argument-resolvers>
</mvc:annotation-driven>
<mvc:interceptors>
<beans:bean class="org.springframework.mobile.device.DeviceResolverHandlerInterceptor"/>
<beans:ref bean="localeChangeInterceptor" />
</mvc:interceptors>
<mvc:default-servlet-handler/>
<resources mapping="/resources/" location="/resources/"/>
<beans:bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<beans:property name="prefix" value="/WEB-INF/views/"/>
<beans:property name="suffix" value=".jsp"/>
</beans:bean>
<!-- If you have locale and all, then you need code below -->
<!-- locale -->
<beans:bean id="messageSource" class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
<beans:property name="basename" value="classpath:/locale/messages"/>
<beans:property name="defaultEncoding" value="UTF-8"/>
</beans:bean>
<!-- default locale -->
<beans:bean id="localeResolver" class="org.springframework.web.servlet.i18n.SessionLocaleResolver">
<beans:property name="defaultLocale" value="de"/>
</beans:bean>
<!-- Change locale via url. -->
<beans:bean id="localeChangeInterceptor" class="org.springframework.web.servlet.i18n.LocaleChangeInterceptor">
<beans:property name="paramName" value="lang"/>
</beans:bean>
<beans:bean id="handlerMapping" class="org.springframework.web.servlet.mvc.support.ControllerClassNameHandlerMapping">
<beans:property name="interceptors">
<beans:list>
<beans:ref bean="localeChangeInterceptor"/>
</beans:list>
</beans:property>
</beans:bean>
</beans:beans>
root-context.xml :
<context:component-scan base-package="com.journaldev.spring">
<context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller" />
</context:component-scan>
<context:property-placeholder location="classpath:application.properties"/>
<beans:bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"
destroy-method="close">
<beans:property name="driverClassName" value="org.postgresql.Driver"/>
<beans:property name="url"
value="jdbc:postgresql://localhost:5432/dbname"/>
<beans:property name="username" value="postgres"/>
<beans:property name="password" value="dbpass"/>
<beans:property name="removeAbandoned" value="true"/>
<beans:property name="removeAbandonedTimeout" value="20"/>
<beans:property name="defaultAutoCommit" value="false"/>
</beans:bean>
<!-- Hibernate 4 SessionFactory Bean definition -->
<beans:bean id="hibernate4AnnotatedSessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<beans:property name="dataSource" ref="dataSource"/>
<beans:property name="packagesToScan" value="com.journaldev.spring.model" />
<beans:property name="hibernateProperties">
<beans:props>
<beans:prop key="hibernate.dialect">org.hibernate.dialect.PostgreSQL9Dialect</beans:prop>
<beans:prop key="hibernate.show_sql">false</beans:prop>
<!-- <beans:prop key="hibernate.jdbc.batch_size">1000</beans:prop>
<beans:prop key="hibernate.order_updates">true</beans:prop>-->
<beans:prop key="hibernate.hbm2ddl.auto">update</beans:prop>
</beans:props>
</beans:property>
</beans:bean>
<beans:bean id="LoginServiceImpl" class="com.journaldev.spring.service.LoginServiceImpl"/>
<task:annotation-driven/>
<tx:annotation-driven transaction-manager="transactionManager"/>
<beans:bean id="transactionManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager">
<beans:property name="sessionFactory" ref="hibernate4AnnotatedSessionFactory"/>
</beans:bean>
</beans:beans>
security-applicationContext.xml :
<security:http pattern="/resources/**" security="none"/>
<security:http create-session="ifRequired" use-expressions="true" auto-config="false" disable-url-rewriting="true">
<security:form-login login-page="/login" login-processing-url="/j_spring_security_check" default-target-url="/dashboard" always-use-default-target="false" authentication-failure-url="/denied" />
<security:remember-me key="_spring_security_remember_me" user-service-ref="userDetailsService" token-validity-seconds="1209600" data-source-ref="dataSource"/>
<security:logout delete-cookies="JSESSIONID" invalidate-session="true" logout-url="/j_spring_security_logout"/>
<security:port-mappings>
<security:port-mapping http="80" https="443"/>
</security:port-mappings>
<security:logout logout-url="/logout" logout-success-url="/" success-handler-ref="myLogoutHandler"/>
<security:session-management session-fixation-protection="migrateSession">
<security:concurrency-control session-registry-ref="sessionRegistry" max-sessions="5" expired-url="/login"/>
</security:session-management>
</security:http>
<!-- Rest authentication, don't edit, delete, add-->
<bean id="springSecurityFilterChain" class="org.springframework.security.web.FilterChainProxy">
<security:filter-chain-map path-type="ant">
<security:filter-chain filters="persistencefilter,authenticationfilter" pattern="/login"/>
<security:filter-chain filters="persistencefilter,logoutfilter" pattern="/logout"/>
<security:filter-chain pattern="/rest/**" filters="persistencefilter,restfilter" />
</security:filter-chain-map>
</bean>
<bean id="persistencefilter" class="org.springframework.security.web.context.SecurityContextPersistenceFilter"/>
<bean id="authenticationfilter" class="com.journaldev.spring.utility.AuthenticationFilter">
<property name="authenticationManager" ref="authenticationManager"/>
<property name="authenticationSuccessHandler" ref="myAuthSuccessHandler"/>
<property name="passwordParameter" value="pass"/>
<property name="usernameParameter" value="user"/>
<property name="postOnly" value="false"/>
</bean>
<bean id="myAuthSuccessHandler" class="com.journaldev.spring.utility.AuthenticationSuccessHandler"/>
<bean id="myLogoutHandler" class="com.journaldev.spring.utility.MyLogoutHandler"/>
<bean id="logoutfilter" class="org.springframework.security.web.authentication.logout.LogoutFilter">
<constructor-arg index="0" value="/"/>
<constructor-arg index="1">
<list>
<bean class="org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler">
<property name="invalidateHttpSession" value="true"/>
<property name="clearAuthentication" value="true"/>
</bean>
<bean id="myLogoutHandler" class="com.journaldev.spring.utility.MyLogoutHandler"/>
</list>
</constructor-arg>
</bean>
<bean id="httpRequestAccessDecisionManager" class="org.springframework.security.access.vote.AffirmativeBased">
<property name="allowIfAllAbstainDecisions" value="false"/>
<property name="decisionVoters">
<list>
<ref bean="roleVoter"/>
</list>
</property>
</bean>
<bean id="roleVoter" class="org.springframework.security.access.vote.RoleVoter"/>
<bean id="restfilter" class="org.springframework.security.web.access.intercept.FilterSecurityInterceptor">
<property name="authenticationManager" ref="authenticationManager"/>
<property name="accessDecisionManager" ref="httpRequestAccessDecisionManager"/>
<property name="securityMetadataSource">
<security:filter-invocation-definition-source>
<security:intercept-url pattern="/rest/**" access="ROLE_USER"/>
</security:filter-invocation-definition-source>
</property>
</bean>
<!-- Rest authentication ends here-->
<!-- queries to be run on data -->
<beans:bean id="rememberMeAuthenticationProvider" class="org.springframework.security.web.authentication.rememberme.PersistentTokenBasedRememberMeServices">
<beans:property name="key" value="_spring_security_remember_me" />
<property name="alwaysRemember" value="true"/>
<beans:property name="tokenRepository" ref="jdbcTokenRepository"/>
<beans:property name="userDetailsService" ref="LoginServiceImpl"/>
</beans:bean>
<!--Database management for remember-me -->
<beans:bean id="jdbcTokenRepository"
class="org.springframework.security.web.authentication.rememberme.JdbcTokenRepositoryImpl">
<beans:property name="createTableOnStartup" value="false"/>
<beans:property name="dataSource" ref="dataSource" />
</beans:bean>
<!-- Remember me ends here -->
<security:authentication-manager alias="authenticationManager">
<security:authentication-provider user-service-ref="LoginServiceImpl">
<security:password-encoder ref="encoder"/>
</security:authentication-provider>
</security:authentication-manager>
<beans:bean id="encoder"
class="org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder">
<beans:constructor-arg name="strength" value="11" />
</beans:bean>
<beans:bean id="daoAuthenticationProvider"
class="org.springframework.security.authentication.dao.DaoAuthenticationProvider">
<beans:property name="userDetailsService" ref="LoginServiceImpl"/>
<beans:property name="passwordEncoder" ref="encoder"/>
</beans:bean>
</beans>
For your reference : The only bean LoginServiceImpl bean I have explicitly declared for login :
#Transactional
#Service("userDetailsService")
public class LoginServiceImpl implements UserDetailsService{
#Autowired private PersonDAO personDAO;
#Autowired private Assembler assembler;
#Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException,DataAccessException {
Person person = personDAO.findPersonByUsername(username.toLowerCase());
if(person == null) { throw new UsernameNotFoundException("Wrong username or password");}
return assembler.buildUserFromUserEntity(person);
}
public LoginServiceImpl() {
}
}
To use my code, you need to add the xml files, I hope you can add the schema mappings on your own, if not, I will paste them. When you are done creating and adding code in XML files, please correct package name to LoginServiceImpl, and in web.xml, point the security-applicationContext.xml and root-context.xml correctly.
Any helpp you need lemme know. And the above configuration is tweaked by M.Denium, so incase I am not there on weekend as I am travelling and he is free, he can help you. Have fun. :-)

It might help to compare your configuration with Spring Boot autoconfiguration for Thymeleaf.
Also, I vaguely remember having similar issue that I resolved by moving sec:authorize in <ul> (instead of <li>). It's been a while, so I don't remember the reason I moved it like that. (Sorry!) Here's a sample of what worked for me (although it was with org.thymeleaf.extras:thymeleaf-extras-springsecurity3).
<ul sec:authorize="isAuthenticated()">
<li><p><span sec:authentication="name">test</span></p> </li>
<li>Logout </li>
</ul>
<ul sec:authorize="isAnonymous()">
<li>Sign Up </li>
<li>Login </li>
</ul>

Finally, I have found the difference with my working spring 3 project. It wasn't the spring version, it was this missing class
public class SpringSecurityInitializer extends
AbstractSecurityWebApplicationInitializer {
}
After I added it the "sec" attributes works correctly.

Related

Spring #Transactional works on Controller but Service has no effect

This is my web.xml
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring/app-root.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<servlet>
<servlet-name>springmvc</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>springmvc</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
This is my springmvc-servlet.xml
<mvc:annotation-driven/>
<mvc:default-servlet-handler/>
<context:component-scan base-package="com.***.***">
<context:exclude-filter type="annotation" expression="org.springframework.stereotype.Service"/>
</context:component-scan>
This is my app-root.xml
<import resource="classpath:spring/app-dao.xml"/>
<import resource="classpath:spring/shiro.xml"/>
<import resource="classpath:spring/app-timer.xml"/>
<import resource="classpath:spring/app-context.xml"/>
This is my app-context.xml
<context:component-scan base-package="com.xinshen.meeting">
<context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
</context:component-scan>
This is my app-datasource.xml
<bean id="adminTxManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
<tx:annotation-driven transaction-manager="adminTxManager"/>
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource"/>
<property name="configLocation" value="classpath:spring/mybatis-config.xml"/>
<!--扫描entity包,使用别名-->
<property name="typeAliasesPackage" value="com.xinshen.meeting.model"/>
<property name="mapperLocations" value="classpath*:mappers/*.xml"/>
<property name="plugins">
<array>
<bean class="com.github.pagehelper.PageHelper">
<property name="properties">
<value>
dialect=mysql
</value>
</property>
</bean>
</array>
</property>
</bean>
<bean id="mapperScannerConfigurer" class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="com.***.***.dao"/>
<property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"/>
</bean>
when I add #Transactional to Controller ,transaction it works but Service it does`t work!
the following pic is #Transactional on Service
enter image description here
the following pic is #Transactional on Controller
enter image description here
I really can`t finger it out,Thanks for help!
I think You have to enable transaction using configuration add this annotation #EnableTransactionManagement in a config class
Create a class for configuration :
#Configuration
#ComponentScan(basePackages = { "Your services package or base package" })
#EnableTransactionManagement
public class MyConfig {
}
If your service are not implementing interface, you need to set proxy-target-class="true" in tag tx:annotation-driven.
You also should add #Transactional on the service class, or on the function invoked by spring bean directly.

Circular view path [index.jsp]: would dispatch back to the current handler URL [/index.jsp] again

It's My Project
enter image description here
It's My spring-mvc.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.1.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.1.xsd
http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.1.xsd">
<context:component-scan base-package="com.SpringDemo.Controller"/>
<!-- Thymeleaf Template Resolver -->
<bean id="templateResolver" class="org.thymeleaf.spring4.templateresolver.SpringResourceTemplateResolver">
<property name="prefix" value="" />
<property name="suffix" value=".html" />
<property name="templateMode" value="HTML" />
<property name="order" value="1" />
</bean>
<bean id="templateEngine" class="org.thymeleaf.spring4.SpringTemplateEngine">
<property name="templateResolver" ref="templateResolver" />
<property name="enableSpringELCompiler" value="true" />
</bean>
<bean class="org.thymeleaf.spring4.view.ThymeleafViewResolver">
<property name="viewNames" value="thymeleaf/*"/>
<property name="templateEngine" ref="templateEngine" />
</bean>
<!-- 对模型视图名称的解析,即在模型视图名称添加前后缀 -->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="viewClass" value="org.springframework.web.servlet.view.JstlView" />
<property name="prefix" value="" />
<!--<property name="suffix" value=".jsp" />-->
<property name="order" value="2" />
<property name="viewNames" value="*.jsp" />
</bean>
<!-- 支持上传文件 -->
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver"/>
</beans>
It's My Controller
#Controller
public class HomeController{
//It's OK
#RequestMapping("/home")
public String showHomePage(Model model){
model.addAttribute("name","spring-mvc");
return "thymeleaf/testTh";
}
//It's WRONG
#RequestMapping("/index")
public ModelAndView test(ModelAndView mv){
mv.addObject("name","erer");
mv.setViewName("index.jsp");
return mv;
}
}
It's My Exception
enter image description here
In's My Web.xml
<servlet>
<servlet-name>springmvc</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet
</servlet-class>
<!-- 加载springMVC的配置文件 -->
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring-mvc.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>springmvc</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
I want that all requests are first passed through the controller.
And then return to the page
Please import spring-boot-starter-thymeleaf
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
I think the problems may be located on the returned view name. Since the view name is the same as the /index path, so maybe it will be dispatched by spring dispatcher again. Maybe you can try to change the view as another name to have a try.

GWT & Thymeleaf & Spring MVC

I have a problem integrating this two technologies.
We have an GWT application integrated with Spring but, additionally to GWT application we need to display HTML files using Thymeleaf for special modules.
The GWT application works well but when I try to run it with Controllers and Thymeleaf enabled this fail.
I've added this to my web.xml to support the Spring Controllers use:
<servlet>
<servlet-name>appServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/conf/spring/controller-context.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>appServlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
And my controller-context.xml has this beans:
<bean id="uiengineTemplateResolver"
class="org.thymeleaf.templateresolver.ServletContextTemplateResolver">
<property name="prefix" value="/uiengine/target/" />
<property name="suffix" value=".html" />
<property name="templateMode" value="HTML5" />
<property name="cacheable" value="false" />
<property name="characterEncoding" value="UTF-8" />
</bean>
<bean id="templateEngine" class="org.thymeleaf.spring3.SpringTemplateEngine">
<property name="templateResolvers">
<array>
<ref bean="uiengineTemplateResolver"/>
</array>
</property>
</bean>
And this at the end:
<context:component-scan base-package="com.enterprise.platform.*.gui" />
There is a way to integrate this two frameworks?
I'll appreciate your help!
Thanks.
I've resolved!
First you need to exclude the main HTML file for GWT from ThymeleafViewResolver so:
controller-context.xml
<bean id="viewResolver" class="org.thymeleaf.spring3.view.ThymeleafViewResolver">
<property name="templateEngine" ref="templateEngine" />
<property name="excludedViewNames">
<array>
<value>gwt-project.html</value>
</array>
</property>
</bean>
Allow the static access for the resources of GWT application:
<mvc:resources mapping="/gwt-project/**" location="/gwt-project/" />
Create a Spring Controller with access root method:
MyController.java
#Controller
public class MyController
{
#RequestMapping(value = "/{appBeanId}", method = RequestMethod.GET)
public String root(#PathVariable String appBeanId, Locale locale,
org.springframework.ui.Model model) {
....
}
}
That's it!.

Spring 3 MVC -- The requested resource is not available

My Spring JSP is not coming up when I call it. Apparently the resource is not available. Here is my controller code.
#Controller
public class BulletinsController {
private List<Bulletin> bulletins;
private BulletinDAO bulletinDAO;
// getters and setters, including autowiring for the BulletinDAO
#RequestMapping(value = "/getApprovedBulletins", method = RequestMethod.POST)
public ModelAndView getApprovedBulletins() {
try {
bulletins = bulletinDAO.getApprovedBulletins();
mav.setViewName("WEB-INF/jsp/EnterBulletin");
if (bulletins != null) {
mav.addObject("bulletins", bulletins);
}
} catch (Exception e) {
System.out.println(e.getMessage());
mav.setViewName("WEB-INF/jsp/FailurePage");
}
return mav;
}
Here is the relevant part of jcbulboard-servlet.xml
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver" />
<property name="url" value="jdbc:mysql://localhost/cpc" />
</bean>
<bean id="bulletinDAO" class="com.dao.BulletinDAO">
<property name="dataSource" ref="dataSource" />
</bean>
<bean id="bulletinsController" class="com.controller.BulletinsController">
<property name="bulletinDAO" ref="bulletinDAO" />
</bean>
Here is my web.xml.
<?xml version="1.0" encoding="UTF-8"?>
<web-app id="WebApp_ID" version="2.4"
xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
<display-name>Job Connections Bulletin Board</display-name>
<servlet>
<servlet-name>jcbulboard</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>jcbulboard</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<welcome-file-list>
<welcome-file>Welcome.jsp</welcome-file>
</welcome-file-list>
</web-app>
Try adding a view resolver to your jcbulboard-servlet.xml:
<bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/jsp/" />
<property name="suffix" value=".jsp" />
</bean>
Instead of
mav.setViewName("WEB-INF/jsp/FailurePage");
It would be
mav.setViewName("FailurePage");
Assuming there is a file named:
WEB-INF/jsp/FailurePage.jsp

Spring 3.0: Handler mapping issue

I am having a trouble mapping a specific URL request to one of the controllers in my project.
the URL is : http://HOSTNAME/api/v1/profiles.json
the war which is deployed is: api.war
the error I get is the following:
[PageNotFound] No mapping found for
HTTP request with URI
[/api/v1/profiles.json] in
DispatcherServlet with name 'action'
The configuration I have is the following: web.xml :
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/applicationContext.xml,/WEB-INF/applicationContext-security.xml</param-value>
</context-param>
<!-- Cache Control filter -->
<filter>
<filter-name>cacheControlFilter</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<!-- Cache Control filter mapping -->
<filter-mapping>
<filter-name>cacheControlFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<!-- Spring security filter -->
<filter>
<filter-name>springSecurityFilterChain</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<!-- Spring security filter mapping -->
<filter-mapping>
<filter-name>springSecurityFilterChain</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<!-- Spring listener -->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<!-- Spring Controller -->
<servlet>
<servlet-name>action</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>action</servlet-name>
<url-pattern>/v1/*</url-pattern>
</servlet-mapping>
The action-servlet.xml:
<mvc:annotation-driven/>
<bean id="contentNegotiatingViewResolver"
class="org.springframework.web.servlet.view.ContentNegotiatingViewResolver">
<property name="favorPathExtension" value="true" />
<property name="favorParameter" value="true" />
<!--
default media format parameter name is 'format'
-->
<property name="ignoreAcceptHeader" value="false" />
<property name="order" value="1" />
<property name="mediaTypes">
<map>
<entry key="html" value="text/html"/>
<entry key="json" value="application/json" />
<entry key="xml" value="application/xml" />
</map>
</property>
<property name="viewResolvers">
<list>
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/jsp/"/>
<property name="suffix" value=".jsp"/>
<property name="viewClass" value="org.springframework.web.servlet.view.JstlView" />
</bean>
</list>
</property>
<property name="defaultViews">
<list>
<bean class="org.springframework.web.servlet.view.json.MappingJacksonJsonView" />
<bean class="org.springframework.web.servlet.view.xml.MarshallingView">
<constructor-arg>
<bean class="org.springframework.oxm.xstream.XStreamMarshaller" />
</constructor-arg>
</bean>
</list>
</property>
</bean>
the application context security:
<sec:http auto-config='true' >
<sec:intercept-url pattern="/login.*" filters="none"/>
<sec:intercept-url pattern="/oauth/**" access="ROLE_USER" />
<sec:intercept-url pattern="/v1/**" access="ROLE_USER" />
<sec:intercept-url pattern="/request_token_authorized.jsp" access="ROLE_USER" />
<sec:intercept-url pattern="/**" access="ROLE_USER"/>
<sec:form-login authentication-failure-url ="/login.html"
default-target-url ="/login.html"
login-page ="/login.html"
login-processing-url ="/login.html" />
<sec:logout logout-success-url="/index.html" logout-url="/logout.html" />
</sec:http>
the controller:
#Controller
public class ProfilesController {
#RequestMapping(value = {"/v1/profiles"}, method = {RequestMethod.GET,RequestMethod.POST})
public void getProfilesList(#ModelAttribute("response") Response response) {
....
}
}
the request never reaches this controller.
Any ideas?
Annotations don't do anything until they are processed. You will need
<context:component-scan base-package="path.to.controllers"/>
as a child of your root "beans" tag in order to get Spring to scan for controllers. Spring will scan for controllers in the base-package and it's descendants.
This tags requires
xmlns:context="http://www.springframework.org/schema/context"
and
xsi:schemaLocation="http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd"
in your root "beans" tag.

Resources