Update booking-mvc to use Spring Java config

This commit is contained in:
Rossen Stoyanchev
2014-02-25 16:13:23 -05:00
parent b948d1075f
commit fa3866854f
12 changed files with 267 additions and 213 deletions

View File

@@ -10,7 +10,7 @@
<properties>
<springsecurity-version>3.2.0.RELEASE</springsecurity-version>
<webflow-version>2.3.3.RELEASE</webflow-version>
<webflow-version>2.4.0.BUILD-SNAPSHOT</webflow-version>
<slf4j-version>1.7.5</slf4j-version>
<thymeleaf-version>2.0.15</thymeleaf-version>
<thymeleaf-extras-tiles2-version>2.0.0</thymeleaf-extras-tiles2-version>

View File

@@ -0,0 +1,46 @@
package org.springframework.webflow.samples.booking.config;
import java.util.Collections;
import javax.persistence.EntityManagerFactory;
import javax.sql.DataSource;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.jdbc.datasource.DriverManagerDataSource;
import org.springframework.orm.jpa.JpaTransactionManager;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;
@Configuration
@EnableTransactionManagement
@ComponentScan(basePackages="org.springframework.webflow.samples.booking")
public class DataAccessConfig {
@Bean
public PlatformTransactionManager transactionManager(EntityManagerFactory emf) {
JpaTransactionManager txManager = new JpaTransactionManager();
txManager.setEntityManagerFactory(emf);
return txManager;
}
@Bean
public LocalContainerEntityManagerFactoryBean entityManagerFactory() {
LocalContainerEntityManagerFactoryBean emf = new LocalContainerEntityManagerFactoryBean();
emf.setDataSource(dataSource());
emf.setJpaVendorAdapter(new HibernateJpaVendorAdapter());
emf.setJpaPropertyMap(Collections.singletonMap("hibernate.session_factory_name", "mySessionFactory"));
return emf;
}
@Bean
public DataSource dataSource() {
DriverManagerDataSource dataSource = new DriverManagerDataSource("jdbc:hsqldb:mem:booking", "sa", "");
dataSource.setDriverClassName("org.hsqldb.jdbcDriver");
return dataSource;
}
}

View File

@@ -0,0 +1,39 @@
package org.springframework.webflow.samples.booking.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.encoding.Md5PasswordEncoder;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.csrf().disable()
.formLogin()
.loginPage("/login")
.loginProcessingUrl("/loginProcess")
.defaultSuccessUrl("/hotels/search")
.failureUrl("/login?login_error=1")
.and()
.logout()
.logoutUrl("/logout")
.logoutSuccessUrl("/logoutSuccess");
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication()
.passwordEncoder(new Md5PasswordEncoder())
.withUser("keith").password("417c7382b16c395bc25b5da1398cf076").roles("USER", "SUPERVISOR").and()
.withUser("erwin").password("12430911a8af075c6f41c6976af22b09").roles("USER", "SUPERVISOR").and()
.withUser("jeremy").password("57c6cbff0d421449be820763f03139eb").roles("USER").and()
.withUser("scott").password("942f2339bf50796de535a384f0d1af3e").roles("USER");
}
}

View File

@@ -0,0 +1,59 @@
package org.springframework.webflow.samples.booking.config;
import java.util.Arrays;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.validation.beanvalidation.LocalValidatorFactoryBean;
import org.springframework.web.servlet.ViewResolver;
import org.springframework.webflow.config.AbstractFlowConfiguration;
import org.springframework.webflow.definition.registry.FlowDefinitionRegistry;
import org.springframework.webflow.engine.builder.support.FlowBuilderServices;
import org.springframework.webflow.executor.FlowExecutor;
import org.springframework.webflow.mvc.builder.MvcViewFactoryCreator;
import org.springframework.webflow.security.SecurityFlowExecutionListener;
@Configuration
public class WebFlowConfig extends AbstractFlowConfiguration {
@Autowired
private WebMvcConfig webMvcConfig;
@Bean
public FlowExecutor flowExecutor() {
return getFlowExecutorBuilder(flowRegistry())
.addFlowExecutionListener(new SecurityFlowExecutionListener(), "*")
.build();
}
@Bean
public FlowDefinitionRegistry flowRegistry() {
return getFlowDefinitionRegistryBuilder(flowBuilderServices())
.setBasePath("/WEB-INF")
.addFlowLocationPattern("/**/*-flow.xml").build();
}
@Bean
public FlowBuilderServices flowBuilderServices() {
return getFlowBuilderServicesBuilder()
.setViewFactoryCreator(mvcViewFactoryCreator())
.setValidator(validator())
.setDevelopmentMode(true)
.build();
}
@Bean
public MvcViewFactoryCreator mvcViewFactoryCreator() {
MvcViewFactoryCreator factoryCreator = new MvcViewFactoryCreator();
factoryCreator.setViewResolvers(Arrays.<ViewResolver>asList(this.webMvcConfig.tilesViewResolver()));
factoryCreator.setUseSpringBeanBinding(true);
return factoryCreator;
}
@Bean
public LocalValidatorFactoryBean validator() {
return new LocalValidatorFactoryBean();
}
}

View File

@@ -0,0 +1,109 @@
package org.springframework.webflow.samples.booking.config;
import java.util.LinkedHashSet;
import java.util.Set;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.DefaultServletHandlerConfigurer;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
import org.springframework.webflow.mvc.servlet.FlowHandlerAdapter;
import org.springframework.webflow.mvc.servlet.FlowHandlerMapping;
import org.springframework.webflow.samples.booking.BookingFlowHandler;
import org.thymeleaf.dialect.IDialect;
import org.thymeleaf.extras.conditionalcomments.dialect.ConditionalCommentsDialect;
import org.thymeleaf.extras.springsecurity3.dialect.SpringSecurityDialect;
import org.thymeleaf.extras.tiles2.dialect.TilesDialect;
import org.thymeleaf.extras.tiles2.spring.web.configurer.ThymeleafTilesConfigurer;
import org.thymeleaf.extras.tiles2.spring.web.view.FlowAjaxThymeleafTilesView;
import org.thymeleaf.spring3.SpringTemplateEngine;
import org.thymeleaf.spring3.view.AjaxThymeleafViewResolver;
import org.thymeleaf.templateresolver.ServletContextTemplateResolver;
@EnableWebMvc
@Configuration
public class WebMvcConfig extends WebMvcConfigurerAdapter {
@Autowired
private WebFlowConfig webFlowConfig;
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/resources/**").addResourceLocations("/", "classpath:/META-INF/web-resources/");
}
@Override
public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
configurer.enable();
}
@Override
public void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController("/").setViewName("intro");
registry.addViewController("/login");
registry.addViewController("/logoutSuccess");
}
@Bean
public FlowHandlerMapping flowHandlerMapping() {
FlowHandlerMapping handlerMapping = new FlowHandlerMapping();
handlerMapping.setOrder(-1);
handlerMapping.setFlowRegistry(this.webFlowConfig.flowRegistry());
return handlerMapping;
}
@Bean
public FlowHandlerAdapter flowHandlerAdapter() {
FlowHandlerAdapter handlerAdapter = new FlowHandlerAdapter();
handlerAdapter.setFlowExecutor(this.webFlowConfig.flowExecutor());
handlerAdapter.setSaveOutputToFlashScopeOnRedirect(true);
return handlerAdapter;
}
@Bean(name="hotels/booking")
public BookingFlowHandler BookingFlowHandler() {
return new BookingFlowHandler();
}
@Bean
public AjaxThymeleafViewResolver tilesViewResolver() {
AjaxThymeleafViewResolver viewResolver = new AjaxThymeleafViewResolver();
viewResolver.setViewClass(FlowAjaxThymeleafTilesView.class);
viewResolver.setTemplateEngine(templateEngine());
return viewResolver;
}
@Bean
public SpringTemplateEngine templateEngine(){
Set<IDialect> dialects = new LinkedHashSet<IDialect>();
dialects.add(new TilesDialect());
dialects.add(new SpringSecurityDialect());
dialects.add(new ConditionalCommentsDialect());
SpringTemplateEngine templateEngine = new SpringTemplateEngine();
templateEngine.setTemplateResolver(templateResolver());
templateEngine.setAdditionalDialects(dialects);
return templateEngine;
}
@Bean
public ServletContextTemplateResolver templateResolver() {
ServletContextTemplateResolver templateResolver = new ServletContextTemplateResolver();
templateResolver.setPrefix("/WEB-INF/");
templateResolver.setTemplateMode("HTML5");
return templateResolver;
}
@Bean
public ThymeleafTilesConfigurer tilesConfigurer() {
ThymeleafTilesConfigurer configurer = new ThymeleafTilesConfigurer();
configurer.setDefinitions("/WEB-INF/**/views.xml");
return configurer;
}
}

View File

@@ -1,38 +0,0 @@
<?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:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.1.xsd">
<!-- Instructs Spring to perfrom declarative transaction management on annotated classes -->
<tx:annotation-driven />
<!-- Drives transactions using local JPA APIs -->
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory" />
</bean>
<!-- Creates a EntityManagerFactory for use with the Hibernate JPA provider and a simple in-memory data source populated with test data -->
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter" />
</property>
<property name="jpaProperties">
<value>
hibernate.session_factory_name=mySessionFactory
</value>
</property>
</bean>
<!-- Deploys a in-memory "booking" datasource populated -->
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="org.hsqldb.jdbcDriver" />
<property name="url" value="jdbc:hsqldb:mem:booking" />
<property name="username" value="sa" />
<property name="password" value="" />
</bean>
</beans>

View File

@@ -1,37 +0,0 @@
<?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:security="http://www.springframework.org/schema/security"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.2.xsd">
<!-- Configure Spring Security -->
<security:http auto-config="true" use-expressions="true">
<security:form-login login-page="/login" login-processing-url="/loginProcess"
default-target-url="/hotels/search" authentication-failure-url="/login?login_error=1" />
<security:logout logout-url="/logout" logout-success-url="/logoutSuccess" />
</security:http>
<!--
Define local authentication provider, a real app would use an external provider (JDBC, LDAP, CAS, etc)
usernames/passwords are:
keith/melbourne
erwin/leuven
jeremy/atlanta
scott/rochester
-->
<security:authentication-manager>
<security:authentication-provider>
<security:password-encoder hash="md5" />
<security:user-service>
<security:user name="keith" password="417c7382b16c395bc25b5da1398cf076" authorities="ROLE_USER, ROLE_SUPERVISOR" />
<security:user name="erwin" password="12430911a8af075c6f41c6976af22b09" authorities="ROLE_USER, ROLE_SUPERVISOR" />
<security:user name="jeremy" password="57c6cbff0d421449be820763f03139eb" authorities="ROLE_USER" />
<security:user name="scott" password="942f2339bf50796de535a384f0d1af3e" authorities="ROLE_USER" />
</security:user-service>
</security:authentication-provider>
</security:authentication-manager>
</beans>

View File

@@ -1,18 +0,0 @@
<?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"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd">
<!-- Scans for application @Components to deploy -->
<context:component-scan base-package="org.springframework.webflow.samples.booking" />
<!-- Imports the configurations of the different infrastructure systems of the application -->
<import resource="webmvc-config.xml" />
<import resource="webflow-config.xml" />
<import resource="data-access-config.xml" />
<import resource="security-config.xml" />
</beans>

View File

@@ -1,37 +0,0 @@
<?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:webflow="http://www.springframework.org/schema/webflow-config"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
http://www.springframework.org/schema/webflow-config http://www.springframework.org/schema/webflow-config/spring-webflow-config-2.3.xsd">
<!-- Executes flows: the entry point into the Spring Web Flow system -->
<webflow:flow-executor id="flowExecutor">
<webflow:flow-execution-listeners>
<webflow:listener ref="securityFlowExecutionListener" />
</webflow:flow-execution-listeners>
</webflow:flow-executor>
<!-- The registry of executable flow definitions -->
<webflow:flow-registry id="flowRegistry" flow-builder-services="flowBuilderServices" base-path="/WEB-INF">
<webflow:flow-location-pattern value="/**/*-flow.xml" />
</webflow:flow-registry>
<!-- Plugs in a custom creator for Web Flow views -->
<webflow:flow-builder-services id="flowBuilderServices" view-factory-creator="mvcViewFactoryCreator"
development="true" validator="validator" />
<!-- Configures Web Flow to use Tiles to create views for rendering; Tiles allows for applying consistent layouts to your views -->
<bean id="mvcViewFactoryCreator" class="org.springframework.webflow.mvc.builder.MvcViewFactoryCreator">
<property name="viewResolvers" ref="tilesViewResolver"/>
<property name="useSpringBeanBinding" value="true" />
</bean>
<!-- Installs a listener to apply Spring Security authorities -->
<bean id="securityFlowExecutionListener" class="org.springframework.webflow.security.SecurityFlowExecutionListener" />
<!-- Bootstraps JSR-303 validation and exposes it through Spring's Validator interface -->
<bean id="validator" class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean"/>
</beans>

View File

@@ -1,70 +0,0 @@
<?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:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="
http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.1.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd">
<!-- Enables controllers mapped with @RequestMapping annotations, formatting annotations @NumberFormat @DateTimeFormat, and JSR 303 style validation -->
<mvc:annotation-driven/>
<mvc:resources mapping="/resources/**" location="/, classpath:/META-INF/web-resources/" />
<mvc:default-servlet-handler />
<!-- Maps request paths to flows in the flowRegistry; e.g. a path of /hotels/booking looks for a flow with id "hotels/booking". -->
<bean class="org.springframework.webflow.mvc.servlet.FlowHandlerMapping">
<property name="order" value="-1"/>
<property name="flowRegistry" ref="flowRegistry" />
</bean>
<!-- Map paths directly to view names without controller processing. Use the view-name attribute if necessary: by convention the view name equals the path without the leading slash -->
<mvc:view-controller path="/" view-name="intro" />
<mvc:view-controller path="/login" />
<mvc:view-controller path="/logoutSuccess" />
<!-- Dispatches requests mapped to flows to FlowHandler implementations -->
<bean class="org.springframework.webflow.mvc.servlet.FlowHandlerAdapter">
<property name="flowExecutor" ref="flowExecutor"/>
<!-- <property name="saveOutputToFlashScopeOnRedirect" value="true"/> -->
</bean>
<!-- Custom FlowHandler for the hotel booking flow -->
<bean name="hotels/booking" class="org.springframework.webflow.samples.booking.BookingFlowHandler" />
<!-- Thymeleaf template resolver -->
<bean id="templateResolver"
class="org.thymeleaf.templateresolver.ServletContextTemplateResolver">
<property name="prefix" value="/WEB-INF/" />
<property name="templateMode" value="HTML5" />
</bean>
<!-- Thymeleaf Template Engine -->
<bean id="templateEngine"
class="org.thymeleaf.spring3.SpringTemplateEngine">
<property name="templateResolver" ref="templateResolver" />
<property name="additionalDialects">
<set>
<bean class="org.thymeleaf.extras.tiles2.dialect.TilesDialect"/>
<bean class="org.thymeleaf.extras.springsecurity3.dialect.SpringSecurityDialect"/>
<bean class="org.thymeleaf.extras.conditionalcomments.dialect.ConditionalCommentsDialect"/>
</set>
</property>
</bean>
<!-- Resolves logical view names returned by Controllers to Tiles; a view name to resolve is treated as the name of a tiles definition -->
<bean id="tilesViewResolver" class="org.thymeleaf.spring3.view.AjaxThymeleafViewResolver">
<property name="viewClass" value="org.thymeleaf.extras.tiles2.spring.web.view.FlowAjaxThymeleafTilesView"/>
<property name="templateEngine" ref="templateEngine"/>
</bean>
<!-- Configures the Tiles layout system using a specific thymeleaf-enabled Tiles Configurer -->
<bean id="tilesConfigurer" class="org.thymeleaf.extras.tiles2.spring.web.configurer.ThymeleafTilesConfigurer">
<property name="definitions">
<list>
<value>/WEB-INF/**/views.xml</value>
</list>
</property>
</bean>
</beans>

View File

@@ -77,31 +77,31 @@
<legend>Login Information</legend>
<p>
<label for="j_username">User:</label>
<label for="username">User:</label>
<br />
<input type="text" name="j_username" id="j_username"
<input type="text" name="username" id="username"
th:value="(${param.login_error} and ${session}) ? ${session[__${lastUsernameKey}__]} : ''" />
</p>
<script type="text/javascript">
// <![CDATA[
Spring.addDecoration(new Spring.ElementDecoration({
elementId : "j_username",
elementId : "username",
widgetType : "dijit.form.ValidationTextBox",
widgetAttrs : { required : true }}));
// ]]>
</script>
<p>
<label for="j_password">Password:</label>
<label for="password">Password:</label>
<br />
<input type="password" name="j_password" id="j_password" />
<input type="password" name="password" id="password" />
</p>
<script type="text/javascript">
// <![CDATA[
Spring.addDecoration(new Spring.ElementDecoration({
elementId : "j_password",
elementId : "password",
widgetType : "dijit.form.ValidationTextBox",
widgetAttrs : { required : true}}));
// ]]>

View File

@@ -4,15 +4,16 @@
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"
version="2.4">
<!-- The master configuration file for this Spring web application -->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
/WEB-INF/config/web-application-config.xml
</param-value>
<param-name>contextClass</param-name>
<param-value>org.springframework.web.context.support.AnnotationConfigWebApplicationContext</param-value>
</context-param>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>org.springframework.webflow.samples.booking.config</param-value>
</context-param>
<!-- Loads the Spring web application context -->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>