Log In
Or create an account ->
Imperial Library
Home
About
News
Upload
Forum
Help
Login/SignUp
Index
Spring in Practice
Willie Wheeler with Joshua White
Copyright
Brief Table of Contents
Table of Contents
Preface
Acknowledgments
About Spring
About this Book
Roadmap
Who should read this book?
Code conventions and downloads
Author Online
About the authors
About the Cover Illustration
Chapter 1. Introducing Spring: the dependency injection container
1.1. What is Spring, and why use it?
Figure 1.1. A high-level block diagram illustrating Spring’s six basic functional areas
1.1.1. The major pieces of the framework
The Core Spring Container
Aspect-oriented programming (AOP)
Data Access/Integration
Web
Test
1.1.2. Why use it?
Figure 1.2. The Core Container
1.2. Flexible configuration via dependency injection
1.2.1. Configuring dependencies the old way
Figure 1.3. JdbcAccountDao specifies a dependency on Apache DBCP’s BasicDataSource, which is a concrete DataSource implementation.
1.2.2. Dependency injection
Figure 1.4. Now JdbcAccountDao has the desired interface dependency on DataSource, but AccountService has dependencies on two concrete classes.
1.2.3. Inversion of control
Listing 1.1. Spring configuration file that specifies object relationships
Figure 1.5. Now the dependencies are interface-based and the concrete classes are configured transparently through Spring.
1.3. A simple bean configuration example
1.3.1. Creating the account domain object
Listing 1.2. Basic account bean, Account.java
1.3.2. Creating the account DAO interface and implementation
Listing 1.3. Reading accounts from a CSV file, CsvAccountDao.java
1.3.3. Configuring CsvAccountDao with Spring
Listing 1.4. Spring configuration file, applicationContext.xml
1.3.4. Creating the account service that finds delinquent accounts
Listing 1.5. AccountService.java: a service responsible for finding delinquent accounts
1.3.5. Wiring up the AccountService to CsvAccountDao
Listing 1.6. Completed Spring configuration file
Figure 1.6. AccountService has an interface-based association with AccountDao, and both depend on Account.
Listing 1.7. ConsoleApp.java, which retrieves the AccountService from Spring
1.4. Wiring beans using XML
1.4.1. An overview of the beans namespace
Wiring Beans Together
Constructor and Setter Injection
Configuring simple bean properties
Externalizing simple properties with a PropertyPlaceholderConfigurer
Listing 1.8. Declaring a PropertyPlaceholderConfigurer to substitute properties
Figure 1.7. Using external properties files to manage configuration for separate environments
1.4.2. Bean scopes
Singleton scope
Figure 1.8. Singleton-scoped beans are shared among dependent class instances.
Prototype scope
Figure 1.9. Prototype-scoped beans are instantiated every time one of their dependent classes is retrieved from the container. But if the dependent class is singleton-scoped, subsequent retrievals of it will return already-cached instances where the prototype-scoped dependency is effectively cached as well (it isn’t reinstantiated).
Request, session, and global session scope
1.4.3. The p namespace
Listing 1.9. Declaring a PropertyPlaceholderConfigurer to substitute properties
1.4.4. The c namespace
1.5. Autowiring and component scanning using annotations
1.5.1. @Autowired
The context namespace
Listing 1.10. Spring configuration modified to support annotations
1.5.2. Stereotype annotations
1.5.3. Component scanning
Listing 1.11. Spring configuration modified to support component scanning
Listing 1.12. Final Spring configuration using component scanning
1.5.4. XML vs. annotations: which is better?
1.6. Summary
Chapter 2. Data persistence, ORM, and transactions
Figure 2.1. The layers involved when implementing a typical Java-based persistence architecture
2.1. Data access using JDBC
Prerequisites
Key technologies
Background
Problem
Solution
Listing 2.1. ContactServiceImpl.java, with JDBC access code
Listing 2.2. ContactRowMapper.java
Listing 2.3. beans-service.xml configuration
Figure 2.2. An app-managed DataSource
Discussion
2.2. Looking up a DataSource with JNDI
Prerequisites
Key technologies
Background
Problem
Solution
Figure 2.3. Getting a container-managed DataSource via JNDI lookup
Listing 2.4. beans-service.xml, with JNDI-based DataSource lookup
Discussion
2.3. Object-relational mapping and transactions via Hibernate
Prerequisites
Key technologies
Background
Problem
Solution
Performing the mapping
Figure 2.4. ORM helps you map Java objects and associations to database entities and relationships.
Figure 2.5. Mapping JPA queries to SQL queries
Listing 2.5. Contact.java, illustrating how to map between Java and the database
Executing queries and updates
Listing 2.6. ContactServiceImpl.java revisited: Hibernate-based implementation
Transaction management
Figure 2.6. A single transaction spanning multiple updates to the database
Table 2.1. Defining transactions with @Transactional elements
Tip
Listing 2.7. beans-service.xml, with Hibernate configuration
Figure 2.7. How applications get access to sessions
Discussion
2.4. Creating a data access layer
Prerequisites
Key technologies
Background
Problem
Solution
Figure 2.8. Class diagram illustrating the relationship between generic framework classes and app-specific implementations
Listing 2.8. Dao.java, a generic DAO interface
Listing 2.9. ContactDao.java: a contact DAO interface
Listing 2.10. AbstractHbnDao.java: a generic base class for implementing DAOs
Listing 2.11. HbnContactDao.java: Hibernate-based DAO for contacts
Listing 2.12. ContactServiceImpl.java without persistence code
Discussion
2.5. Working with JPA (optional)
Prerequisites
Key technologies
Background
Problem
Solution
Figure 2.9. DAOs call the Hibernate API directly.
Figure 2.10. DAOs call JPA interfaces. You can bind an arbitrary persistence provider to the interface (EclipseLink JPA, OpenJPA, Hibernate, and so on).
Listing 2.13. JpaContactDao.java: a JPA-based DAO
Listing 2.14. beans-service.xml with a JPA-based persistence configuration
Discussion
2.6. Spring Data JPA overview (optional)
Prerequisites
Key technologies
Background
Problem
Solution
Listing 2.15. ContactDao.java, revised to use Spring Data JPA
Listing 2.16. beans-service.xml, revised to use Spring Data JPA
Discussion
2.7. Summary
Chapter 3. Building web applications with Spring Web MVC
3.1. Spring Web MVC background
3.1.1. A review of the model-view-controller (MVC) pattern
Figure 3.1. A conceptual view of control flow in web-based model-view-controller applications
3.1.2. What is Spring Web MVC?
Note
3.1.3. An architectural overview of Spring Web MVC
Figure 3.2. A conceptual view of control flow in Spring Web MVC
3.2. Creating your first Spring Web MVC application
3.2.1. Configuring the application
Listing 3.1. Simple DispatcherServlet configuration in web.xml
Listing 3.2. /WEB-INF/main-servlet.xml, the DispatcherServlet’s local app context
3.2.2. A simple domain object
Listing 3.3. Member.java
3.2.3. Writing a basic controller
Listing 3.4. RosterController.java, the simple controller
Warning
3.2.4. Implementing the master and details views
Listing 3.5. /WEB-INF/jsp/roster/list.jsp, a roster master page
Listing 3.6. /WEB-INF/jsp/roster/member.jsp, a member details page
3.3. Serving and processing forms
3.3.1. Using domain objects as form beans
3.3.2. Adding a controller
Listing 3.7. NomineeController.java, a simple form controller
3.3.3. Adding a form JSP and a “thanks” JSP
Listing 3.8. /WEB-INF/jsp/nominee/form.jsp
Listing 3.9. /WEB-INF/jsp/nominee/thanks.jsp
3.3.4. Updating the application context
3.3.5. Adding redirect-after-post behavior
3.3.6. Adding form-binding whitelisting
3.3.7. Adding form validation
3.4. Configuring Spring Web MVC: web.xml
Listing 3.10. Simple DispatcherServlet configuration in web.xml
Note
3.5. Configuring Spring Web MVC: the application context
Table 3.1. DispatcherServlet strategy interfaces and default implemetations
3.5.1. Configuring HandlerMappings
Table 3.2. HandlerMapping implementations
BeanNameUrlHandlerMapping
ControllerClassNameHandlerMapping
DefaultAnnotationHandlerMapping
SimpleUrlHandlerMapping
Using Multiple Handler Mappings at Once
HandlerInterceptors
Figure 3.3. Control flow in a HandlerExecutionChain
Listing 3.11. How to intercept controllers with HandlerInterceptors
3.5.2. Configuring HandlerAdapters
3.5.3. Configuring HandlerExceptionResolvers
3.5.4. Configuring ViewResolvers
InternalResourceViewResolver, the Default View Resolution Strategy
redirect: and forward:
Beannameviewresolver
Xmlviewresolver
Other ViewResolvers and Views
Chaining ViewResolvers
3.5.5. Configuring a RequestToViewNameTranslator
3.5.6. Configuring other resolvers
3.6. Spring Mobile technology preview
3.6.1. A brief anatomy of an HTTP request
Simulating a mobile device
3.6.2. Detecting a mobile device with Spring Mobile
3.6.3. Configuring Spring Mobile
Listing 3.12. web.xml
Listing 3.13. main-servlet.xml
Listing 3.14. Configuring WebArgumentResolvers
3.6.4. Handling site preferences
3.6.5. Using JavaScript frameworks for enhanced look and feel
Figure 3.4. The Contact List sample application when viewed by a normal browser
Figure 3.5. The Contact List sample application when viewed by a mobile device
3.6.6. Switching to a separate mobile site
mDot SiteSwitcher
dotMobi SiteSwitcher
3.7. Related technologies
3.7.1. Spring Web Flow
3.7.2. Spring JavaScript
3.7.3. Spring Faces
3.7.4. Spring Security
3.7.5. RESTful web services
3.8. Summary
Chapter 4. Basic web forms
4.1. Displaying a web form
Prerequisites
Key technologies
Background
Problem
Solution
Figure 4.1. The simple web-based registration form that you’ll build in this recipe
Creating an account form bean
Listing 4.1. AccountForm.java, a form bean for user accounts
Creating a web controller
Listing 4.2. AccountController.java to handle user registrations
Creating the view pages
Listing 4.3. registrationForm.jsp: view to display your registration form
Figure 4.2. Formbinding in action. Stars show where form fields and bean properties are bound together.
Configuring the app
Listing 4.4. beans-web.xml: web tier configuration
Figure 4.3. The redirect-after-post implementation for successful registrations
Discussion
4.2. Externalizing strings in the view
Prerequisite
Key technologies
Background
Problem
Solution
Creating a resource bundle for the messages
Listing 4.5. messages.properties: resource bundle for externalized strings
Adding a message source to beans-web.xml
Replacing the hardcoded strings with references
Listing 4.6. Updating registrationForm.jsp to use external messages
Discussion
4.3. Validating form data
Prerequisite
Key technologies
Background
Problem
Solution
Figure 4.4. Validation in Spring Web MVC. The form-binding API handles field filtering, JSR 303 handles bean validation, and there’s a Spring validation API for custom logic.
Field filtering via @InitBinder and WebDataBinder
Validating the form data
Step 1. Placing a JSR 303 implementation on the classpath
Step 2. Adding bean-validation annotations to the form bean
Listing 4.7. AccountForm.java, with validation annotations (updates listing 4.1)
Step 3. Updating the controller to validate the form data
Listing 4.8. AccountController.java, updated to validate form data (updates listing 4.2)
Step 4. Configuring error messages
Listing 4.9. ValidationMessages.properties, for JSR 303 error messages
Step 5. Displaying validation errors in the view
Figure 4.5. The revised registration form, with a global error message and field-level error messages
Listing 4.10. registrationForm.jsp, updated with validation error messages
Step 6. Configuring the app for validation
Discussion
4.4. Saving form data
Prerequisites
Key technologies
Background
Problem
Solution
Figure 4.6. Bean-dependency diagram for saving user registration data. We’re including infrastructure for both Hibernate- and JDBC-based persistence.
Creating a database schema for storing user accounts
Listing 4.11. User account table (MySQL)
Annotating the account model for persistence
Listing 4.12. Account.java with JPA annotations for persistence
Creating the account data access object
Listing 4.13. HbnAccountDao.java, backed by both Hibernate and JDBC
Creating the account service
Listing 4.14. AccountServiceImpl.java: service implementation
Adding a new error message for duplicate usernames
Updating the controller to save accounts using the service
Creating a new application context configuration for persistence
Listing 4.15. beans-service.xml: application context configuration
Updating web.xml to point to the new app context configuration
Discussion
4.5. Summary
Chapter 5. Enhancing Spring MVC applications with Web Flow
5.1. Is Spring Web Flow right for you?
5.2. An overview of Spring Web Flow
5.2.1. Defining a flow
Figure 5.1. In this simplified search flow, users start by entering search criteria and transition to a state where they can view their search results. The flow transitions to the end state after the user selects an item.
Listing 5.1. Defining a flow
5.2.2. The five types of states
Table 5.1. The five types of state in SWF
View state
Action state
Decision state
End state
Subflow state
5.2.3. Transitions between states
Listing 5.2. Defining transitions
5.2.4. Flow data
Declaring variables
The five variable scopes
Figure 5.2. If you don’t explicitly identify which scope a variable is in, SWF starts looking in the request scope and continues looking in the flash, view, flow, and conversation scopes until the variable is found.
5.3. The Spring Soccer Club demo application
Figure 5.3. Before users are allowed to register, you first ask if they have registered in the past. If they haven’t, users go directly to the registration page. If they have registered previously, the user is able to search for this registration. If they still are unable to find their existing registration, users can register again.
5.3.1. Installing and configuring SWF
Prerequisites
Key Technologies
Background
Problem
Solution
Basic Spring MVC configuration
Listing 5.3. web.xml: DispatcherServlet
Listing 5.4. dispatcherServlet-context.xml
Listing 5.5. HelloWorldController
Listing 5.6. /WEB-INF/jsp/helloWorld.jsp
Figure 5.4. If everything is working correctly, you should see “Hello World” from Spring MVC.
Basic SWF configuration
Listing 5.7. /WEB-INF/spring/web/webflowContext.xml
Customizing flow builder services
Configuring the flow executor
Configuring the flow registry
Integrating with Spring MVC
Figure 5.5. If everything is working correctly, you should see “Hello World” from SWF.
5.3.2. Creating flows with different state types
Prerequisites
Key Technologies
Background
Problem
Solution
Figure 5.6. Being able to search for and select an existing player may be useful in several places in a larger application. As a result, you’ll separate the findExistingPlayer functionality into its own subflow. It will be called from the main registration flow.
Creating the findExistingPlayer subflow
Listing 5.8. /WEB-INF/flows/findExistingPlayer/findExistingPlayer-flow.xml
Figure 5.7. Showing the result of the displayFindExistingPlayerResult view state
Listing 5.9. /WEB-INF/flows/findExistingPlayer/displayFindExistingPlayerResult.jsp
Listing 5.10. /WEB-INF/flows/findExistingPlayer/findExistingPlayerForm.jsp
Creating the registration flow
Listing 5.11. /WEB-INF/flows/registration/registration-flow.xml
5.4. Using action classes
Prerequisites
Key Technologies
Background
Problem
Solution
Figure 5.8. Although several classes implement the Action interface out of the box, we’ll focus on AbstractAction, MultiAction, and FormAction.
Listing 5.12. FindExistingPlayerAction.java
AbstractAction
MultiAction
Listing 5.13. PlayerActions.java
FormAction
Listing 5.14. FormAction: webflowContext.xml
5.5. Form data binding
Prerequisites
Key Technologies
Background
Problem
Solution
5.6. Form validation
Prerequisites
Key Technologies
Background
Problem
Solution
Bootstrapping a JSR-303 Implementation
Configuring SWF to use JSR-303 Validation
Listing 5.15. com.springinpractice.ch05.form.AccountForm
Mapping error codes to messages in a properties file
5.7. Flow and state inheritance
Prerequisites
Key Technologies
Background
Problem
Solution
Flow inheritance
Listing 5.16. \WEB-INF\flows\common\common-flow.xml
Listing 5.17. \WEB-INF\flows\inheritanceDemo\inheritance-demo-flow.xml
State Inheritance
More Information
5.8. Securing web flows
Prerequisites
Key technologies
Background
Problem
Solution
Configuring Spring Security
Listing 5.18. web.xml
Listing 5.19. \WEB-INF\spring\applicationContext-security.xml
Configuring the SecurityFlowExecutionListener
Listing 5.20. \WEB-INF\config\webflowContext.xml
Securing Flows, transitions, and states
Listing 5.21. \WEB-INF\flows\securityDemo\security-demo-flow.xml
5.9. Summary
Chapter 6. Authenticating users
6.1. Implementing login and logout with remember-me authentication
Prerequisites
Key technologies
Background
Problem
Solution
Figure 6.1. The default login page, complete with Submit Query (or Submit, depending on the browser) button. The page is styled with CSS.
Configure Spring Security
Listing 6.1. beans-security.xml, your Spring Security configuration
Authentication managers, providers, and user details services
Figure 6.2. A class diagram for AuthenticationManager and ProviderManager
Figure 6.3. The AuthenticationProvider hierarchy, which includes tons of provider options
Figure 6.4. UserDetailsService hierarchy, containing DAOs used by the DaoAuthenticationProvider
Figure 6.5. Bean dependency diagram for listing 6.1
Configuring web.xml for web security
Listing 6.2. Configuring web.xml with the Spring Security filter
Figure 6.6. Filter proxying for injectable servlet filters
Figure 6.7. DelegatingFilterProxy sequence diagram. This is a partial view; we’ve suppressed the full filter chain. Filter 1, Filter 2, and so on refer to filters in the chain.
Creating the appropriate links in your JSPs
Listing 6.3. User information and shared navigation in subhead.jspf
Discussion
6.2. Customizing the login page
Prerequisite
Key technologies
Background
Problem
Solution
Creating the login form JSP
Figure 6.8. A custom login page
Listing 6.4. Custom login form, login.jsp, whose appearance you control
Adding a view controller to beans-web.xml
Figure 6.9. From request path to view with a view controller
Modifying the <form-login> element in beans-security.xml
Updating the login link in the navigation
Discussion
6.3. Implementing an always-resident login form
Prerequisites
Key technologies
Background
Problem
Figure 6.10. A login form that displays on every page until the user logs in
Solution
Modifying subhead.jspf to include the login form
Listing 6.5. subhead.jspf updated to include an always-resident login form
Creating a login-required page
Creating a login-failed page
Spring Web MVC configuration
Spring security configuration
Discussion
6.4. Sourcing user data from a database
Prerequisite
Key technologies
Background
Problem
Solution
Figure 6.11. Bean dependency graph for a JDBC-backed authentication manager
Creating the database tables
Figure 6.12. ERD for the default user schema. Each user has zero or more roles.
Exposing the database using JNDI
Looking up the DataSource from Spring
Working with JdbcDaoImpl
Table 6.1. Default SQL queries that JdbcDaoImpl uses to retrieve user data
Discussion
6.5. Customizing the user database schema
Prerequisites
Key technologies
Background
Problem
Solution
Figure 6.13. ERD for a custom user schema. Compare with figure 6.12.
Discussion
6.6. Using a custom user service and user principal
Prerequisites
Key technologies
Background
Problem
Solution
Figure 6.14. Class diagram for the DaoAuthenticationProvider. In this recipe, you’ll implement the adapters that allow you to use the account service from recipe 4.4 as a UserDetailsService.
Adapting the Account domain object to the UserDetails interface
Listing 6.6. UserDetailsAdapter.java, which adapts Account to UserDetails
Creating a DAO for retrieving passwords
Listing 6.7. JdbcUserDetailsDao.java for password lookups
Adapting the AccountService interface to the UserDetailsService interface
Listing 6.8. UserDetailsServiceAdapter.java, backed by AccountService
Updating the Spring configuration to use the new UserDetailsService
Listing 6.9. beans-data.xml, updated to support the custom user service
Listing 6.10. beans-service.xml for service configuration
Figure 6.15. Bean dependency graph for DaoAuthenticationProvider and its dependencies
Updating subhead.jspf to display the user’s full name
Discussion
6.7. Secure user passwords in the database
Prerequisites
Key technologies
Background
Problem
Solution
Figure 6.16. Hashing a plaintext password into a digest for improved security at rest
Hashing passwords before storing them in the database
Defending against dictionary attacks using salt
Figure 6.17. Improving security at rest by incorporating a variable salt
Discussion
6.8. Auto-authenticating the user after a successful registration
Prerequisites
Key technologies
Background
Problem
Solution
Discussion
6.9. Summary
Chapter 7. Authorizing user requests
Figure 7.1. Relationship between the types of authorization in Spring Security 3
Table 7.1. Authorization combinations and their corresponding recipes
Authorization targets
Authorization styles
7.1. Authorizing Java methods using authentication levels, roles, and permissions
Prerequisite
Key technologies
Background
Problem
Solution
Table 7.2. SpEL predicates for defining authentication- and role-based access controls
Listing 7.1. ForumServiceImpl.java with security annotations
Key technique 1: Whitelisting
Tip
Key technique 2: Separate roles and permissions
Figure 7.2. User schema that separates roles from permissions
Figure 7.3. Users, roles, and permissions for the sample application
Discussion
7.2. Authorizing JSP views using authentication levels, roles, and permissions
Prerequisite
Key technologies
Background
Problem
Solution
Figure 7.4. Navigation display based on user authentication levels, roles, and permissions
Listing 7.2. subhead.jspf, containing the app’s primary page navigation
Another way to specify a <security:authorize> access condition
Discussion
7.3. Authorizing web resources using authentication levels, roles, and permissions
Prerequisite
Key technologies
Background
Problem
Solution
Listing 7.3. Defining access controls on URLs in beans-security.xml.
Updating the page navigation to eliminate rule duplication
Discussion
7.4. Authorizing method invocations based on ACLs
Prerequisite
Key technologies
Background
Figure 7.5. An ACL for a message. The author has one set of permissions with respect to the message, and other users have other permissions.
Figure 7.6. With rolebased authorization, a user might have permission to (say) edit messages in general. With ACL-based authorization, you can set user edit permissions on a message-by-message basis.
Problem
Solution
Defining domain object ACLs
Figure 7.7. E/R diagram for the Spring Security ACL schema
Tip
Figure 7.8. How Spring Security links its ACL schema to its user schema. This allows Spring Security to support custom app objects because the Spring Security user schema uses Java interfaces.
Table 7.3. Sample acl_sid rows (SIDs)
Figure 7.9. How Spring Security ties its ACL schema to domain objects
Table 7.4. Representing messages generally using acl_class
Table 7.5. Representing message 106 using acl_object_identity (some columns suppressed)
Table 7.6. ACL permissions and their numeric values
Table 7.7. Granting Daniel permission to edit message 106 (some columns suppressed)
Defining ACL-based access rules for Java methods
Table 7.8. Annotations for controlling access to Java methods
Table 7.9. SpEL expressions for domain object security
Configuring domain object security
Listing 7.4. beans-security-acl.xml, supporting domain object security
Figure 7.10. ACL configuration as a bean dependency graph
Table 7.10. AclAuthorizationStrategyImpl constructor arguments
Optimizing ACL definitions
Figure 7.11. Creating separate ACEs for each message. Don’t do this!
Figure 7.12. Best practice: establish parent/child relationships, then inherit permissions
Manipulating ACLs programmatically
Listing 7.5. Using MutableAclService to manage message ACLs
Discussion
7.5. Displaying web navigation and content based on ACLs
Prerequisite
Key technologies
Background
Problem
Solution
The message JSP
Listing 7.6. message.jsp, showing how you show or suppress privileged features
Try it out
Discussion
7.6. Summary
Chapter 8. Communicating with users and customers
8.1. Create a web-based Contact Us form
Prerequisites
Key technologies
Background
Problem
Solution
Figure 8.1. This is the simple contact form that you’re creating.
Figure 8.2. Key contact service dependencies: a standard controller/service/DAO stack
Spring web MVC controller and form JSP
Listing 8.1. ContactController.java, a Spring web MVC controller
Listing 8.2. contactForm.jsp, a JSP to present the contact form
A simple service bean
Listing 8.3. ContactServiceImpl.java, the service bean
UserMessage and persistence
Listing 8.4. UserMessage.java, a domain model for (surprise!) user messages
Database schema
Discussion
8.2. Autogenerate an email response and email notification
Prerequisites
Key technologies
Background
Problem
Solution
Listing 8.5. src/main/resources/velocity/contactConfirm.vm
ContactServiceImpl revisited
Figure 8.3. Equipping the ContactService to send email
Listing 8.6. New and improved ContactServiceImpl.java
Dependencies
Creating and sending email
Application configuration
Figure 8.4. Key bean dependencies for recipe 8.2.
Listing 8.7. Additions to beans-service.xml
Discussion
Note
8.3. Speeding up autogenerated emails
Prerequisites
Key technologies
Background
Problem
Solution
Figure 8.5. Refactored design to allow you to send email asynchronously: (1) save the form data, (2) invoke the mail-sender proxy, (3) call the mail sender asynchronously, and (4) send the email.
Refactoring ContactServiceImpl
Listing 8.8. The newly refactored ContactServiceImpl
Listing 8.9. ContactMailSender, which you invoke asynchronously using @Async
Configuring the app for asynchronous tasks
Listing 8.10. Additions to beans-services.xml to support @Async
Table 8.1. <task:executor> configuration
Discussion
8.4. Allowing users to subscribe to a mailing list
Prerequisites
Key technologies
Background
Problem
Solution
Figure 8.6. User flow when subscribing to the mailing list.
The controller
Listing 8.11. Handling subscriptions with MailingListController.java
The subscription form
Listing 8.12. Subscription form, subscribeForm.jsp
The service bean
Figure 8.7. Using a digest to authenticate subscribers without having to store subscriber-specific secrets
Listing 8.13. MailingListServiceImpl.java, with secure subscriptions
Application context configuration
Discussion
Note
8.5. Publishing a news feed
Prerequisites
Key technologies
Background
Problem
Solution
The View
Listing 8.14. RSS news feed view: RssNewsFeedView.java
The controller
Listing 8.15. Minimalistic NewsController.java
The application context
Discussion
8.6. Summary
Chapter 9. Creating a rich-text comment engine
9.1. Creating a basic user comment engine
Prerequisites
Key technologies
Background
Problem
Solution
Figure 9.1. The comment engine, with a comment list and a place to enter comments
Figure 9.2. Comment engine bean-dependency graph. This shows what the comment service needs to filter comments and send notification emails.
Database schema
Figure 9.3. Comment engine E/R diagram. This simple schema allows you to attach comments to arbitrary targets.
Domain objects, ORM, and validation
Listing 9.1. Comment.java domain object
Listing 9.2. CommentTarget.java, representing anything that can be commented on
The CommentServiceImpl service bean
Listing 9.3. CommentServiceImpl.java, a service bean
Comment text filtering
Listing 9.4. PlainTextFilter.java: a simple strategy for filtering text
JSP fragment for displaying a comment list
Listing 9.5. /WEB-INF/jspf/comment/list.jspf
JSP fragment for posting a new comment
Listing 9.6. /WEB-INF/jspf/comment/post.jspf
Bean configuration
Listing 9.7. /src/main/resources/spring/beans-service.xml
Discussion
9.2. Integrating the comment engine with an article-delivery service
Prerequisites
Key technologies
Background
Problem
Solution
Figure 9.4. A bean-dependency graph showing the relationship between the comment service from recipe 9.1 and the article service from this recipe.
Figure 9.5. E/R diagram for the comment engine, with an article table added. You connect the tables using a foreign key in the article table that points at comment_target.
A simple Article class, showing how to integrate with CommentTarget
Listing 9.8. Article.java: an example of something that can be commented on
Data access object for articles
Listing 9.9. HbnArticleDao.java
The ArticleServiceImpl service bean
Listing 9.10. ArticleServiceImpl.java service bean
Spring Web MVC @Controller
Listing 9.11. ArticleController.java
An article JSP that uses the two comment JSP fragments
Listing 9.12. /WEB-INF/jsp/articles/articlePage.jsp
Discussion
9.3. Adding rich-text support to the comment engine
Prerequisites
Key technologies
Background
Problem
Solution
Figure 9.6. The comment engine after adding PageDown
Figure 9.7. Bean-dependency graph for the version of the comment engine
Application context configuration and Spring resources
Listing 9.13. beans-service.xml configuration
A rich-text filter for converting Markdown to HTML
Listing 9.14. RichTextFilter.java: converts Markdown to sanitized HTML[7]
Listing 9.15. JsRuntimeSupport.java, providing load() and print() implementations
Discussion
9.4. Testing the HTML filter
Prerequisites
Key Technologies
Background
Problem
Solution
Listing 9.16. RichTextFilterTest.java: integration test based on JUnit
Discussion
9.5. Summary
Chapter 10. Integration testing
Figure 10.1. A simple contact-management application for which you’ll write integration tests
10.1. Configuring Maven for integration testing
Prerequisites
Key technologies
Background
Problem
Solution
Figure 10.2. Overview of the default Maven lifecycle
Build Helper Maven plug-in
Listing 10.1. Adding new source and resource directories to Maven
Failsafe Maven plug-in
Figure 10.3. The key Maven lifecycle phases for integration testing
Listing 10.2. Binding integration test goals to the default lifecycle
Table 10.1. Default Surefire and Failsafe filename pattern matching
Maven dependencies
Listing 10.3. Integration-testing dependencies
Discussion
10.2. Writing transactional happy-path integration tests
Prerequisites
Key technologies
Background
Problem
Solution
Structuring app configuration to facilitate integration testing
Figure 10.4. You’ll write integration tests for the stack that start from the controller and go all the way back to the database.
Figure 10.5. Bean-dependency diagram for a simple contact-management application. This is the normal app configuration, not the integration-test configuration.
Figure 10.6. Spring app context configuration for integration tests. The DataSourceInitializer sets up the test database by running DDL and test data DML. The controller, service, and DAO are suppressed because they’re exactly the same as in figure 10.5.
Listing 10.4. beans-datasource.xml, for normal app usage
Listing 10.5. beans-datasource-it.xml, for integration testing
SQL scripts for integration testing
Listing 10.6. sip10-schema-mysql.sql: integration test DDL
Listing 10.7. sip10-test-data-mysql.sql: test data
Happy-path integration test #1: getting a contact
Figure 10.7. A details page prepopulated with subterranean, homesick contact data
Listing 10.8. ContactControllerIT.java: integration test case
Figure 10.8. Test cases use JUnit and Spring TestContext framework annotations. The tests run in the Failsafe integration-test execution environment.
Happy-path integration test #2: updating a contact
Listing 10.9. Testing contact updates
Figure 10.9. The TestContext framework automatically rolls back transactions after each test completes, ensuring that the test database is in a clean state for the next test.
Happy-path integration test #3: deleting a contact
Listing 10.10. Testing contact deletion
Discussion
10.3. Verifying that code under test throws an exception
Prerequisites
Key technologies
Background
Problem
Solution
Listing 10.11. Elaborating ContactControllerIT.java
Discussion
10.4. Creating integration tests that verify performance
Prerequisites
Key technologies
Background
Problem
Solution
Listing 10.12. Adding a time-bounded test to ContactControllerIT.java
Figure 10.10. A visual comparison between setting timeouts using @Test(timeout = ...) and @Timed
Listing 10.13. Updating Failsafe definition in pom.xml
Figure 10.11. Without environment=ci, the test runner skips two tests.
Figure 10.12. No skipped tests
Discussion
10.5. Ignoring a test
Prerequisites
Key technologies
Background
Problem
Solution
Listing 10.14. Ignoring a test using @Ignore
Discussion
10.6. Running integration tests against an embedded database
Prerequisites
Key technologies
Background
Problem
Solution
Figure 10.13. Bean dependencies using the embedded database
Listing 10.15. sip10-schema-hsql.sql: integration test DDL for HSQLDB
Listing 10.16. beans-service.xml, revisited
Listing 10.17. beans-datasource-it.xml, revisited
Listing 10.18. beans-datasource.xml, revisited
Discussion
10.7. Summary
Chapter 11. Building a configuration management database
Figure 11.1. A hypothetical configuration management architecture built around a CMDB, supporting auto-deployment to dev servers on commit
11.1. Creating a simple configuration item
Prerequisites
Key technologies
Background
Figure 11.2. The deployer updates configuration in place on all target servers, requiring lots of manual, error-prone work. Not a best practice.
Figure 11.3. The deployer edits the configuration in one place, and then the automation pushes it through to the target servers.
Problem
Solution
Creating a CI abstraction and base CI
Listing 11.1. CI.java: the CI interface
Listing 11.2. AbstractCI: a base class for implementing CIs
Creating the application CI
Listing 11.3. Application.java: the application CI
Creating the application DAO
Listing 11.4. ApplicationRepository.java: the DAO interface
Spring configuration
Listing 11.5. beans-service.xml configuration
Discussion
11.2. Creating related configuration items
Prerequisites
Key technologies
Background
Problem
Solution
Enhancing the application CI to support relationships
Listing 11.6. Expanding Application.java to support relationships
Building out the other CIs and their relationships
Listing 11.7. Module.java, representing a module of code
Listing 11.8. Package.java, representing a module package
Listing 11.9. Team.java, with team members suppressed
Listing 11.10. ApplicationTeam.java relationship entity
Tip
Creating DAOs for the new CIs
Listing 11.11. ModuleRepository.java
Listing 11.12. PackageRepository.java
Create a service abstraction and base service
Listing 11.13. CIService.java service interface
Listing 11.14. AbstractCIService.java: base class for CI service beans
Creating a package service
Listing 11.15. PackageService.java
Listing 11.16. PackageServiceImpl.java service bean
Discussion
11.3. Adding a RESTful web service
Prerequisites
Key technologies
Background
Problem
Solution
Augmenting the package and module CIs
Listing 11.17. ListWrapper.java: supporting XML lists
Listing 11.18. AbstractCI.java, updated to support XML and JSON mappings
Listing 11.19. Updating Package.java to support XML and JSON mappings
Listing 11.20. Updating Module.java to support XML and JSON mappings
Creating web service endpoints
Listing 11.21. Generic read-only endpoints in AbstractCrudController.java
Listing 11.22. PackageCrudController.java: extending base CRUD controller
Configuring Spring
Listing 11.23. beans-web.xml configuration for RESTful web service
Tip
Discussion
11.4. Updating the CMDB after successful builds
Prerequisites
Key technologies
Background
Problem
Solution
Creating a “create package” endpoint on the CMDB
Listing 11.24. PackageCrudController.java with endpoint for creating packages
Listing 11.25. ZkybaseClient.java: client for the Zkybase web service
Writing a Maven plug-in that calls the “create package” endpoint
Listing 11.26. PackageMojo.java: Maven plug-in
Discussion
11.5. Sourcing public GitHub data
Prerequisites
Key technologies
Background
Problem
Solution
Figure 11.4. Displaying GitHub repo watchers from your UI
Setting up Maven
Calling Spring Social GitHub from a controller
Listing 11.27. ApplicationScmController.java
Configuring the app
Getting GitHub data using Spring’s RestTemplate
Listing 11.28. RepoTemplate.java
Discussion
11.6. Sourcing private GitHub data
Prerequisites
Key technologies
Background
Problem
Solution
Connecting to GitHub via OAuth 2
Note
Figure 11.5. OAuth 2 flow, with Zkybase as the consumer and GitHub as the service provider
Figure 11.6. The dance begins.
Figure 11.7. GitHub OAuth 2 authorization verification
Figure 11.8. The Zkybase user account page after establishing the current user’s connection to GitHub
Figure 11.9. Zkybase displays the repository hooks it read from GitHub on behalf of the current Zkybase user.
Creating a database table for user connections
Listing 11.29. Creating the userconnection table
Creating the user account service bean
Listing 11.30. UserAccountServiceImpl.java
Retrieving repository hooks
Listing 11.31. ApplicationServiceImpl.java
Displaying the user account page
Listing 11.32. userAccountDetails.jsp, for account details
Configuring Spring
Listing 11.33. beans-social.xml: Spring Social configuration
Figure 11.10. Spring Social GitHub bean dependency diagram
Discussion
11.7. Encrypting access tokens for production use
Prerequisites
Key technologies
Background
Problem
Solution
Listing 11.34. Updated beans-social.xml with development and production profiles
Discussion
11.8. Summary
Chapter 12. Building an article-delivery engine
Figure 12.1. Chapter roadmap and architectural relationships
12.1. Storing articles in a content repository
Prerequisities
Key technologies
Background
Problem
Solution
JCR basics
Figure 12.2. JCR application architecture. Content apps make calls against the standardized JCR API, and repository vendors provide compliant implementations.
Article repository overview
Figure 12.3. An article CMS architecture with the bare essentials. The development environment has authoring, version control, and a packager. The runtime environment supports importing article packages (for example, article content, assets, and metadata) and delivering it to users. In this recipe, JCR is the runtime article repository.
Setting up the Jackrabbit content repository
Building the domain objects
Listing 12.1. Article.java: simple domain object for articles
Listing 12.2. Page.java: page domain object
Building the data access layer
Figure 12.4. DAO class diagram
Listing 12.3. ArticleDao.java: data access object interface for articles
Listing 12.4. JcrArticleDao.java: JCR-based DAO implementation
Listing 12.5. ArticleMapper.java: converts between articles and JCR nodes
Listing 12.6. beans-jcr.xml: Spring beans configuration for the JCR repository
Figure 12.5. Bean-dependency diagram for the JCR-based article repository
Discussion
12.2. Creating a web-based article-delivery engine
Prerequisities
Key technologies
Background
Problem
Solution
Building the controller
Listing 12.7. ArticleController.java: web controller for articles
Building the master list and details view JSPs
Figure 12.6. A screenshot of the article master list
Listing 12.8. articleList.jsp: displays the master list of articles
Figure 12.7. The article details view must show page navigation, and the first page shows the title, author, publication date, and description.
Listing 12.9. articlePage.jsp: displays a single article page with page navigation
Listing 12.10. pageNav.jsp: page navigation
Importing articles
Listing 12.11. Example of an article.xml file for the article package
Figure 12.8. How an article package on the user’s machine ends up as an article in the article repository
Figure 12.9. The article-upload form
Figure 12.10. How ArticleConverter converts an article package to an Article
Listing 12.12. ArticleConverter.java: extracts an Article from the file upload
Configuring the application
Listing 12.13. beans-web.xml: Spring beans web configuration
Figure 12.11. The combined beans-jcr.xml and beans-web.xml bean-dependency diagram
Discussion
12.3. Storing articles in a document repository
Prerequisites
Key technologies
Background
Problem
Solution
Step 1: Setting up a MongoDB instance
Step 2: Removing JCR code
Step 3: Creating a new ArticleDao interface
Listing 12.14. ArticleDao.java, revised to work with Spring Data MongoDB
Step 4: Updating ArticleController
Step 5: Creating beans-mongodb.xml
Listing 12.15. beans-mongodb.xml: Spring beans configuration for MongoDB
Figure 12.12. The bean-dependency diagram for the Spring Data MongoDB configuration
Step 6: Updating web.xml
Discussion
12.4. Summary
Chapter 13. Enterprise integration
Figure 13.1. Overview of your help desk system and its integrations as they appear at the end of the chapter
13.1. A whirlwind tour of Spring Integration
Figure 13.2. Two channels dependency-injected into an endpoint. The channels correspond to pipes in the pipes-and-filters architectural style, and the endpoint corresponds to a filter.
13.2. Integrating applications via a shared database
Prerequisites
Key Technologies
Background
Problem
Solution
Figure 13.3. Application integration through a shared database
Getting a single app to work with multiple databases
Figure 13.4. The portal and help desk applications share customer data through direct access to a shared customer database. For smallscale integrations, this can be a clean and simple solution.
Listing 13.1. beans-repo.xml: configuration for the ticket database
Listing 13.2. beans-repo-portal.xml: configuration for the customer database
Configuring and running the applications
Discussion
13.3. Decoupling applications with RESTful web services
Prerequisites
Key Technologies
Background
Problem
Solution
Figure 13.5. The point-to-point integration architecture for this recipe. The apps hide their databases from one another but expose RESTful web service APIs for data access.
Implementing a RESTful web service using Spring Data REST
Listing 13.3. UserRepository: SDJ repository annotated for exporting by SDR
Listing 13.4. Defining RepositoryRestExporterServlet in web.xml
Implementing data transfer objects using Spring HATEOAS
Note
Listing 13.5. CustomerResource.java: HATEOAS-oriented DTO
Listing 13.6. CustomerResources.java: another HATEOAS-oriented DTO
Implementing a RESTful client using RestTemplate
Listing 13.7. PortalGateway: hides messaging details from the help desk app
Listing 13.8. PortalGatewayImpl: uses RestTemplate to get customer data
Running the applications
Discussion
Figure 13.6. The point-to-point integration strategy scales as O(n2). Managing all the integrations can become unwieldy over time.
13.4. Implementing a message bus using RabbitMQ and Spring Integration
Prerequisites
Key Technologies
Background
Problem
Solution
Figure 13.7. Integrating applications via a centralized RabbitMQ message broker. This improves scalability and enhances decoupling.
Message buses and canonical data models
Listing 13.9. Ticket.java: DTO for tickets
Revisiting the gateway interfaces
Listing 13.10. TicketGateway.java: using CDM DTOs
Reimplementing the Portal’s TicketGateway using Spring Integration
Implementing self-service ticket creation: portal’s outbound messaging
Figure 13.8. A portal-integration pipeline supporting fire-and-forget ticket creation. The channel adapter pushes ticket-creation messages onto the bus.
Listing 13.11. beans-integration.xml: portal application
Implementing self-service ticket creation: help desk’s inbound messaging
Figure 13.9. A help desk integration pipeline that receives ticket-creation messages from the bus and creates tickets in the help desk database
Listing 13.12. beans-integration.xml: help desk application
Listing 13.13. TicketTransformer.java
Implementing the finders: portal’s outbound messaging
Figure 13.10. The portal’s outbound pipeline with support for the TicketGateway’s finder methods
Listing 13.14. beans-integration.xml: portal application
Implementing the finders: help desk’s inbound messaging
Figure 13.11. The help desk’s inbound pipeline to support the TicketGateway’s finder methods. Although it’s not shown here, each chain contains a service activator followed by a transformer.
Listing 13.15. beans-integration.xml: help desk application
Discussion
13.5. Sourcing tickets from an IMAP store
Prerequisites
Key Technologies
Background
Problem
Solution
Figure 13.12. You’ll add an emailbased ticket channel using SI’s support for inbound email.
Figure 13.13. You’ll augment the inbound pipeline to include support for IMAP messages.
Spring Integration configuration
Listing 13.16. Help desk’s beans-integration.xml, with support for inbound email
Updating the TicketTransformer
Listing 13.17. Updated version of TicketTransformer.java
Try the code
Discussion
13.6. Send confirmation messages over SMTP
Prerequisites
Key Technologies
Background
Problem
Solution
Figure 13.14. Adding outbound SMTP messaging to support confirmation emails
Figure 13.15. Modifying the pipeline to support confirmation emails whenever somebody creates a new ticket. No change to the app is required.
Listing 13.18. Help desk’s beans-integration.xml, with support for confirmation emails
Listing 13.19. TicketTransformer.java with a transform method for confirmation emails
Discussion
13.7. Summary
Chapter 14. Creating a Spring-based “site-up” framework
14.1. Circuit-breaker overview
Figure 14.1. Fault propagation from service to client, and from client to service
Figure 14.2. The breaker on the left is in the closed state, which is normal. Requests flow freely across a closed breaker. The breaker on the right is open. Requests can’t flow across an open breaker.
Figure 14.3. Circuit-breaker state diagram showing all three states and their transitions
14.2. Creating a circuit-breaker template and callback
Prerequisites
Key technologies
Background
Figure 14.4. Sequence diagram illustrating the template pattern
Problem
Solution
A little framework setup
Listing 14.1. Guard.java: template interface for circuit breakers
Listing 14.2. GuardCallback.java: corresponding callback interface
Listing 14.3. AbstractGuard.java: simple base implementation
Implementing a circuit breaker using a template
Listing 14.4. CircuitBreakerTemplate.java, part 1: breaker configuration
Listing 14.5. CircuitBreakerTemplate.java, part 2: breaker state
Figure 14.5. Sequence diagram illustrating tripping, timeouts, and resetting
Creating a sample integration point
Figure 14.6. HomeController uses a circuit breaker to protect against problems with the MessageService.
Listing 14.6. Flakinator.java: component to make the service flaky
Listing 14.7. Message.java: simple message object
Listing 14.8. MessageService.java: simple message service interface
Listing 14.9. MessageServiceImpl.java: simple message service implementation
Listing 14.10. HomeController.java: home-page controller
Listing 14.11. home.jsp: home-page view
Configuring the circuit breaker
Listing 14.12. beans-kite.xml: circuit-breaker configuration
Running the app
Discussion
14.3. Exposing the circuit breaker as a JMX MBean
Prerequisites
Key technologies
Background
Problem
Solution
Listing 14.13. Updating AbstractGuard.java for JMX
Listing 14.14. Updating CircuitBreakerTemplate.java for JMX
Listing 14.15. Updating beans-kite.xml for JMX
Running the app
Using a JMX console to connect to the app
Figure 14.7. Viewing and editing MBean attributes using Java VisualVM
Figure 14.8. Management operations via Java VisualVM
Discussion
14.4. Supporting AOP-based configuration
Prerequisites
Key technologies
Background
Problem
Solution
Implementing breaker advice
Figure 14.9. Interceptor-based advice using the breaker template
Listing 14.16. GuardListInterceptor.java advice implementation
Listing 14.17. GuardListSource.java: interface for obtaining guard lists
Listing 14.18. DefaultGuardListSource.java: returns a configured guard list
Reverting the client code
Listing 14.19. MessageServiceImpl.java, revised to remove breaker code
Updating the Spring configuration
Listing 14.20. beans-kite.xml, illustrating declarative configuration via AOP
Discussion
14.5. Supporting custom namespaces
Prerequisites
Key technologies
Background
Problem
Solution
Creating the pointer files
Creating an XML schema
Listing 14.21. kite-1.0.xsd: DSL definition
Listing 14.22. kite-1.0.xsd, continued, with guard list advice definition
Creating a NamespaceHandler and BeanDefinitionParsers
Listing 14.23. KiteNamespaceHandler.java: entry point into the DSL
Table 14.1. BeanDefinitionParser base implementations
Listing 14.24. CircuitBreakerParser.java: parses the breaker DSL into breakers
Listing 14.25. GuardListAdviceParser.java
Figure 14.10. BeanDefinitionParser hierarchy and the parsers
Updating the sample app
Listing 14.26. Namespace-based beans-kite.xml configuration
Discussion
14.6. Supporting annotation-based configuration
Prerequisites
Key technologies
Background
Problem
Solution
Creating the annotation
Listing 14.27. GuardedBy.java for annotation-based configuration
Implementing a new CircuitBreakerSource and pointcut
Figure 14.11. The GuardListSource hierarchy, which includes two concrete implementations
Listing 14.28. AnnotationGuardListSource.java, for annotation-based sourcing
Listing 14.29. GuardListSourcePointcut.java
Creating the BeanDefinitionParser
Listing 14.30. AnnotationConfigParser.java core
Figure 14.12. Complex parsers often implement BeanDefinitionParser directly.
Listing 14.31. AopAutoProxyConfigurer.java helper methods
Updating the NamespaceHandler
Updating the client code
Listing 14.32. MessageServiceImpl.java, with annotations
Updating the client configuration
Listing 14.33. beans-kite.xml, updated for annotations
Discussion
14.7. Summary
Appendix. Working with the sample code
A.1. IDE and environment setup
A.2. How the code is organized
A.3. Getting the code
Option 1: Download the tarball or ZIP
Option 2: Clone the Git repository
A.4. Building the code
A.5. Configuring the app
A.6. Running the app
Index
SYMBOL
A
B
C
D
E
F
G
H
I
J
K
L
M
N
O
P
Q
R
S
T
U
V
W
X
List of Figures
List of Tables
List of Listings
← Prev
Back
Next →
← Prev
Back
Next →