This document provides an overview of Spring's support for building multi-client web applications. It discusses Spring's servlet support including the Servlet 3.0 initializer classes. It also covers Spring MVC, building mobile-friendly applications, native Android development with Spring, REST support, and securing applications with Spring Security. The document contains examples of core Spring features like controllers and uses diagrams to illustrate classic Spring MVC architecture. It aims to demonstrate these techniques through examples and code snippets.
3. Servlet 3.0 Initializer Classes
public class SampleWebApplicationInitializer implements WebApplicationInitializer {
public void onStartup(ServletContext sc) throws ServletException {
AnnotationConfigWebApplicationContext ac = new AnnotationConfigWebApplicationContext();
ac.setServletContext(sc);
ac.scan( “a.package.full.of.services”, “a.package.full.of.controllers” );
sc.addServlet("spring", new DispatcherServlet(ac));
}
}
Wednesday, June 5, 13
4. Servlet Support in Spring
§ Spring Dispatcher Servlet provides a lot of powerful support
§ lots of convenient utility objects
HttpRequestHandlers supports remoting: Caucho, Resin, JAX RPC, etc.
DelegatingFilterProxy javax.filter.Filter that delegates to a Spring-managed lifecycle
HandlerInterceptor wraps requests to HttpRequestHandlers
ServletWrappingController lets you force requests to a servlet through the Spring Handler chain
OncePerRequestFilter ensures that an action only occurs once
WebApplicationContextUtils has a static method to look up the current ApplicationContext given a ServletContext
Wednesday, June 5, 13
5. Spring Web Framework Support
•Spring Faces for JSF 1 and 2
•Struts support for Struts 1
•Tapestry, Struts 2, Stripes, Wicket, Vaadin, Play framework, etc.
•GWT, Flex
Wednesday, June 5, 13
7. classic Spring MVC application architecture
DispatcherServlet controller
view
template
delegate
request
delegate
rendering of
response
render
response
return
control
model
model
incoming
requests
return
response
Wednesday, June 5, 13
8. the anatomy of a Spring MVC controller
@Controller
public class CustomerController {
// ...
}
Wednesday, June 5, 13
9. the anatomy of a Spring MVC controller
@Controller
public class CustomerController {
@RequestMapping(value= “/url/of/my/resource”)
public String processTheRequest() {
// ...
return “home”;
}
}
GET http://127.0.0.1:8080/url/of/my/resource
Wednesday, June 5, 13
10. the anatomy of a Spring MVC controller
@Controller
public class CustomerController {
@RequestMapping(value= “/url/of/my/resource”, method = RequestMethod.GET)
public String processTheRequest() {
// ...
return “home”;
}
}
GET http://127.0.0.1:8080/url/of/my/resource
Wednesday, June 5, 13
11. the anatomy of a Spring MVC controller
@Controller
public class CustomerController {
@RequestMapping(value=“/url/of/my/resource”, method = RequestMethod.GET)
public String processTheRequest( HttpServletRequest request) {
String contextPath = request.getContextPath();
// ...
return “home”;
}
}
GET http://127.0.0.1:8080/url/of/my/resource
Wednesday, June 5, 13
12. the anatomy of a Spring MVC controller
@Controller
public class CustomerController {
@RequestMapping(value=“/url/of/my/resource”, method = RequestMethod.GET)
public String processTheRequest( @RequestParam(“search”) String searchQuery){
// ...
return “home”;
}
}
GET http://127.0.0.1:8080/url/of/my/resource?search=searchQuery
Wednesday, June 5, 13
13. the anatomy of a Spring MVC controller
@Controller
public class CustomerController {
@RequestMapping(value=“/url/of/my/{id}”, method = RequestMethod.GET)
public String processTheRequest( @PathVariable(“id”) Long id){
// ...
return “home”;
}
}
GET http://127.0.0.1:8080/url/of/my/12345
Wednesday, June 5, 13
14. the anatomy of a Spring MVC controller
@Controller
public class CustomerController {
@Inject private CustomerService service ;
@RequestMapping(value=“/url/of/my/{id}”, method = RequestMethod.GET)
public String processTheRequest(Model model, @PathVariable(“id”) Long id){
model.addAttribute(“customer”, service.getCustomerById( id ) );
return “home”;
}
}
GET http://127.0.0.1:8080/url/of/my/12345
Wednesday, June 5, 13
15. the anatomy of a Spring MVC controller
@Controller
public class CustomerController {
@RequestMapping(value=“/url/of/my/{id}”, method = RequestMethod.GET)
public String processTheRequest( ... ){
return “home”;
}
}
Wednesday, June 5, 13
16. the anatomy of a Spring MVC controller
@Controller
public class CustomerController {
@RequestMapping(value=“/url/of/my/{id}”, method = RequestMethod.GET)
public View processTheRequest( ... ){
return new XsltView(...);
}
}
Wednesday, June 5, 13
17. the anatomy of a Spring MVC controller
@Controller
public class CustomerController {
@RequestMapping(value=“/url/of/my/{id}”, method = RequestMethod.PUT)
public ResponseEntity<byte[]> processTheRequest(UriComponentsBuilder componentsBuilder){
byte[] bytesToReturn = ...
HttpHeaders headers = new HttpHeaders();
headers.setLocation( componentsBuilder.toUri() );
return new ResponseEntity<byte[]>(
bytesToReturn, headers, HttpStatus.CREATED
);
}
}
Wednesday, June 5, 13
25. Roy Fielding’s “REST”
• The term Representational State Transfer was introduced and
defined in 2000 by Roy Fielding in his doctoral dissertation.
§ Takeaways:
• Use HTTP methods explicitly.
• Be stateless
• an HTTP resource is uniquely described by its URL
Wednesday, June 5, 13
27. RestTemplate
§ Google search example
§ Multiple parameters
RestTemplate restTemplate = new RestTemplate();
String url = "http://example.com/hotels/{hotel}/bookings/{booking}";
String result = restTemplate.getForObject(url, String.class, "42", “21”);
RestTemplate restTemplate = new RestTemplate();
String url = "https://ajax.googleapis.com/ajax/services/search/web?v=1.0&q={query}";
String result = restTemplate.getForObject(url, String.class, "SpringSource");
Wednesday, June 5, 13
28. the anatomy of a Spring MVC REST controller
@Controller
public class CustomerController {
@Inject private CustomerService service ;
@RequestMapping(value=”/url/of/my/resource”, method = RequestMethod.GET)
public @ResponseBody Customer processTheRequest( ... ) {
Customer c = service.getCustomerById( id) ;
return c;
}
}
GET http://127.0.0.1:8080/url/of/my/resource
Wednesday, June 5, 13
29. the anatomy of a Spring MVC REST controller
@Controller
public class CustomerController {
@RequestMapping(value=”/url/of/my/resource”, method = RequestMethod.POST)
public void processTheRequest( @RequestBody Customer customer ) {
// ...
}
}
POST http://127.0.0.1:8080/url/of/my/resource
Wednesday, June 5, 13
30. A Fly in the Ointment
•modern browsers only speak GET and POST
<filter>
<filter-name>hiddenHttpMethodFilter</filter-name>
<filter-class>org.springframework.web.filter.HiddenHttpMethodFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>hiddenHttpMethodFilter</filter-name>
<url-pattern>/</url-pattern>
<servlet-name>appServlet</servlet-name>
</filter-mapping>
Wednesday, June 5, 13
33. Be Where Your Users Are
§ Best strategy? Develop Native
• Fallback to client-optimized web applications
§ Spring MVC mobile client-specific content
negotiation and rendering
• for other devices
Wednesday, June 5, 13
34. Registering Spring Android
@EnableWebMvc
@Configuration
public class MobileConfiguration extends WebMvcConfigurerAdapter {
@Override
public void addArgumentResolvers(List< HandlerMethodArgumentResolver > argumentResolvers) {
argumentResolvers.add(new DeviceHandlerMethodArgumentResolver());
}
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new DeviceResolverHandlerInterceptor());
}
}
Wednesday, June 5, 13
37. What is Spring for Android?
§ does not prescribe a dependency injection solution
§ provides an implementation of RestTemplate
Wednesday, June 5, 13
38. Some Native Android Code
public Customer updateCustomer(long id, String firstName, String lastName) {
RestTemplate restTemplate = new RestTemplate();
String url = “http://...8080/url/of/my/{id}”;
Customer input = new Customer(id, firstName, lastName);
ResponseEntity<Customer> re = restTemplate.postForEntity( url, input, Customer.class, id);
HttpStatus statusOfRequest = re.getStatusCode();
if(statusOfRequest.equals( HttpStatus.OK )){
Customer payloadOfResponse = re.getBody();
return payloadOfResponse;
}
...
}
Wednesday, June 5, 13
39. Make Work with
§ install android development kit http://developer.android.com/sdk/index.html
§ set up m2e-android http://rgladwell.github.io/m2e-android/
Wednesday, June 5, 13
44. What Problems Does OAuth Solve?
• new world of many, cooperating web services
• some web services may have a user context
• this user context can refer to a centrally managed identity (single sign-on)
• user passwords should be decoupled from the permissions a client is given
Wednesday, June 5, 13
48. Key Components of Spring Social
§ Connection Factories
• Creates connections; Handles back-end of authorization flow
§ Connection Repository
• Persists connections for long-term use
§ Connection Factory Locator
• Used by connect controller and connection repository to find connection factories
§ API Bindings
• Perform requests to APIs, binding to domain objects, error-handling (Facebook, Twitter, etc.)
§ ConnectController
• Orchestrates the web-based connection flow
§ ProviderSignInController
• Signs a user into an application based on an existing connection and links it to the local system
Wednesday, June 5, 13
52. The ConnectController
@Bean
public ConnectController connectController(
ConnectionFactoryLocator connectionFactoryLocator,
ConnectionRepository connectionRepository) {
return new ConnectController(
connectionFactoryLocator,
connectionRepository);
}
establishes an OAuth-secured connection with the service
provider and returns an access token
Wednesday, June 5, 13
53. The ProviderSignInController
@Bean
public ProviderSignInController providerSignInController(
final UsersConnectionRepository usersConnectionRepository,
final ConnectionFactoryLocator connectionFactoryLocator) {
SignInAdapter signInAdapter = ...
ProviderSignInController psic = new ProviderSignInController(
connectionFactoryLocator, usersConnectionRepository, signInAdapter);
psic.setSignInUrl("/crm/signin.html");
psic.setPostSignInUrl("/crm/customers.html");
psic.setSignUpUrl("/crm/signup.html");
return psic;
}
}
establishes an OAuth-secured connection with the service
provider and links it to a local account
Wednesday, June 5, 13
56. Security is Hard, Spring Security is Easy
§ Spring Security provides security services for the Spring framework
§ integrates with backend identity provider services like LDAP, JAAS, OAuth, etc.
§ API Bindings
• there are lots of implementations of the Spring Security API that can be used in terms of a particular backend
identity provider service.
§ can be used to secure web applications
• form submissions, XSS-protection, resource protection
§ can be used to secure method invocations
§ authentication and authorization API
§ cryptography implementations
Wednesday, June 5, 13
57. Install Spring Security in your web.xml or Application Initializer
public class CrmWebApplicationInitializer implements WebApplicationInitializer {
@Override
public void onStartup(ServletContext servletContext) throws ServletException {
String name = "springSecurityFilterChain";
Filter filter = new DelegatingFilterProxy();
FilterRegistration.Dynamic filterRegistration = servletContext.addFilter(name, filter);
filterRegistration.addMappingForUrlPatterns(null, true, "/");
filterRegistration.addMappingForServletNames(null, true, "spring");
filterRegistration.setAsyncSupported(true);
}
Wednesday, June 5, 13
58. Tell Spring About Your Identities: Inline
<sec:authentication-manager>
<sec:authentication-provider>
<sec:user-service>
<sec:user name="jlong" authorities="read" />
<sec:user name="mchang" authorities="read,write" />
</sec:user-service>
</sec:authentication-provider>
</sec:authentication-manager>
Wednesday, June 5, 13
59. Tell Spring About Your Identities With a Custom Implementation
<sec:authentication-manager>
<sec:authentication-provider user-service-ref = “customUserService” />
</sec:authentication-manager>
Wednesday, June 5, 13
60. Tell Spring About Your Identities with LDAP
<sec:authentication-manager>
<sec:ldap-authentication-provider ... />
</sec:authentication-manager>
Wednesday, June 5, 13
61. Secure Access to Certain Web Resources
<sec:http auto-config="true" use-expressions="true">
<sec:intercept-url pattern="/secured/**" access="hasRole('ROLE_USER')" />
<sec:intercept-url pattern="/**" access="isAnonymous()" />
<sec:anonymous />
</sec:http>
Wednesday, June 5, 13
62. Install a Sign-In Form
<sec:http auto-config="true" use-expressions="true">
<sec:intercept-url pattern="/secured/**" access="hasRole('ROLE_USER')" />
<sec:intercept-url pattern="/**" access="isAnonymous()" />
<sec:anonymous />
<sec:form-login
login-page="/crm/signin.html"
default-target-url="/crm/profile.html"
authentication-failure-url="/crm/signin.html?error=true" />
</sec:http>
Wednesday, June 5, 13
68. What Problems Does OAuth Solve?
• new world of many, cooperating web services
• some web services may have a user context
• this user context can refer to a centrally managed identity (single sign-on)
• user passwords should be decoupled from the permissions a client is given
Wednesday, June 5, 13
69. When Should I Use Spring Security OAuth?
§ when you want to build an OAuth authentication server
§ when your REST API has a user context that needs to be managed
Wednesday, June 5, 13
70. Spring Security OAuth
§ Extension to Spring Security
• originally a community contribution (now officially part of the project)
§ Features...
• endpoint management for OAuth service types
• token management (persistence, authentication)
• integrations for the web, as well as through standard Spring Security
Wednesday, June 5, 13
71. Tell Spring About the Clients That Might Connect
<oauth:client-details-service id="clientDetailsService">
<oauth:client
client-id="html5-crm"
scope="read,write"
authorities="ROLE_USER"
authorized-grant-types="authorization_code,implicit"
resource-ids="crm"/>
<oauth:client
client-id="android-crm"
scope="read,write"
authorities="ROLE_USER"
authorized-grant-types="authorization_code,implicit"
resource-ids="crm"/>
</oauth:client-details-service>
Wednesday, June 5, 13
72. Tell Spring About the Clients That Might Connect
<oauth:authorization-server
client-details-service-ref="clientDetailsService"
token-services-ref="tokenServices">
<oauth:authorization-code/>
<oauth:implicit/>
<oauth:refresh-token/>
<oauth:client-credentials/>
<oauth:password/>
</oauth:authorization-server>
@Bean
public InMemoryTokenStore tokenStore() {
return new InMemoryTokenStore();
}
@Bean
public DefaultTokenServices tokenServices(
InMemoryTokenStore tokenStore,
ClientDetailsService clientDetailsService) {
DefaultTokenServices defaultTokenServices = new DefaultTokenServices();
defaultTokenServices.setTokenStore(tokenStore);
defaultTokenServices.setSupportRefreshToken(true);
defaultTokenServices.setClientDetailsService(clientDetailsService);
return defaultTokenServices;
}
Wednesday, June 5, 13
73. Tell Spring About Which Resources It’s Protecting
<oauth:resource-server id="resourceServerFilter"
resource-id="crm" token-services-ref="tokenServices"/>
<sec:http pattern="/api/**"
create-session="never"
entry-point-ref="oauthAuthenticationEntryPoint"
access-decision-manager-ref="accessDecisionManager">
<sec:anonymous enabled="true"/>
<sec:custom-filter ref="resourceServerFilter" before="PRE_AUTH_FILTER"/>
...
Wednesday, June 5, 13
74. Tell Spring About Which Resources It’s Protecting
<oauth:resource-server id="resourceServerFilter"
resource-id="crm" token-services-ref="tokenServices"/>
<sec:http pattern="/api/**"
create-session="never"
entry-point-ref="oauthAuthenticationEntryPoint"
access-decision-manager-ref="accessDecisionManager">
<sec:anonymous enabled="true"/>
<sec:custom-filter ref="resourceServerFilter" before="PRE_AUTH_FILTER"/>
<sec:intercept-url pattern="/api/users/**/photo" method="GET"
access="IS_AUTHENTICATED_ANONYMOUSLY"/>
<sec:intercept-url pattern="/api/users" method="GET" access="IS_AUTHENTI
CATED_ANONYMOUSLY"/>
<sec:intercept-url pattern="/api/**"
access="ROLE_USER,SCOPE_READ"/>
Wednesday, June 5, 13
75. Optional: Set Up an OAuth-Aware RestTemplate
<oauth:rest-template id="crmRestTemplate" resource="crm" />
Wednesday, June 5, 13
76. Enable Access to Certain OAuth-Context Objects in SpEL
<sec:global-method-security pre-post-annotations="enabled" proxy-target-class="true">
<sec:expression-handler ref="oauthExpressionHandler"/>
</sec:global-method-security>
<oauth:expression-handler id="oauthExpressionHandler"/>
<oauth:web-expression-handler id="oauthWebExpressionHandler"/>
Wednesday, June 5, 13