/* |
3 |
* Copyright (C) 2010 Archie L. Cobbs. All rights reserved. |
4 |
* |
5 |
* $Id: AutowiringApplicationServlet.java 19 2010-02-04 18:09:30Z archie $ |
6 |
*/ |
7 |
|
8 |
package com.example; |
9 |
|
10 |
import com.vaadin.Application; |
11 |
import com.vaadin.terminal.gwt.server.ApplicationServlet; |
12 |
|
13 |
import javax.servlet.ServletConfig; |
14 |
import javax.servlet.ServletException; |
15 |
import javax.servlet.http.HttpServletRequest; |
16 |
|
17 |
import org.springframework.beans.BeansException; |
18 |
import org.springframework.beans.factory.config.AutowireCapableBeanFactory; |
19 |
import org.springframework.web.context.WebApplicationContext; |
20 |
import org.springframework.web.context.support.WebApplicationContextUtils; |
21 |
|
22 |
/** |
23 |
* {@link ApplicationServlet} that autowires and configures the {@link Application} |
24 |
* objects it creates using the associated Spring {@link WebApplicationContext}. |
25 |
* This allows a Vaadin application to be configured normally as a Spring bean. |
26 |
* |
27 |
* <p> |
28 |
* For example, annotations such as |
29 |
* <code>{@link org.springframework.beans.factory.annotation.Autowired @Autowired}</code>, |
30 |
* <code>{@link org.springframework.beans.factory.annotation.Required @Required}</code>, etc. |
31 |
* and interfaces such as {@link org.springframework.beans.factory.BeanFactoryAware BeanFactoryAware}, |
32 |
* etc. will work on your {@link Application} instances. |
33 |
* </p> |
34 |
* |
35 |
* <p> |
36 |
* An example of "direct" use of this servlet in conjunction with Spring's |
37 |
* {@link org.springframework.web.context.ContextLoaderListener ContextLoaderListener}: |
38 |
* <blockquote><pre> |
39 |
* <!-- Spring context loader --> |
40 |
* <listener> |
41 |
* <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> |
42 |
* </listener> |
43 |
* |
44 |
* <!-- Vaadin servlet --> |
45 |
* <servlet> |
46 |
* <servlet-name>myapp</servlet-name> |
47 |
* <servlet-class>com.example.AutowiringApplicationServlet</servlet-class> |
48 |
* <init-param> |
49 |
* <param-name>application</param-name> |
50 |
* <param-value>some.spring.configured.Application</param-value> |
51 |
* </init-param> |
52 |
* <init-param> |
53 |
* <param-name>productionMode</param-name> |
54 |
* <param-value>true</param-value> |
55 |
* </init-param> |
56 |
* </servlet> |
57 |
* <servlet-mapping> |
58 |
* <servlet-name>myapp</servlet-name> |
59 |
* <url-pattern>/*</url-pattern> |
60 |
* </servlet-mapping> |
61 |
* </pre></blockquote> |
62 |
* </p> |
63 |
* |
64 |
* <p> |
65 |
* An example that creates a Spring MVC "controller" bean for use with Spring's |
66 |
* {@link org.springframework.web.servlet.DispatcherServlet DispatcherServlet}: |
67 |
* <blockquote><pre> |
68 |
* <!-- Activate Spring annotation support --> |
69 |
* <context:annotation-config/> |
70 |
* |
71 |
* <!-- Define controller bean for Vaadin application --> |
72 |
* <bean id="applicationController" class="org.springframework.web.servlet.mvc.ServletWrappingController" |
73 |
* p:servletClass="com.example.AutowiringApplicationServlet"> |
74 |
* <property name="initParameters"> |
75 |
* <props> |
76 |
* <prop key="application">some.spring.configured.Application</prop> |
77 |
* <prop key="productionMode">true</prop> |
78 |
* </props> |
79 |
* </property> |
80 |
* </bean> |
81 |
* </pre></blockquote> |
82 |
* |
83 |
* @see org.springframework.web.servlet.mvc.ContextLoaderListener |
84 |
* @see org.springframework.web.servlet.DispatcherServlet |
85 |
* @see org.springframework.web.servlet.mvc.ServletWrappingController |
86 |
* @see AutowireCapableBeanFactory |
87 |
*/ |
88 |
public class AutowiringApplicationServlet extends ApplicationServlet { |
89 |
|
90 |
private WebApplicationContext webApplicationContext; |
91 |
|
92 |
/** |
93 |
* Initialize this servlet. |
94 |
* |
95 |
* @throws ServletException if there is no {@link WebApplicationContext} associated with this servlet's context |
96 |
*/ |
97 |
@Override |
98 |
public void init(ServletConfig config) throws ServletException { |
99 |
super.init(config); |
100 |
try { |
101 |
this.webApplicationContext = WebApplicationContextUtils.getRequiredWebApplicationContext(config.getServletContext()); |
102 |
} catch (IllegalStateException e) { |
103 |
throw new ServletException("could not locate containing WebApplicationContext"); |
104 |
} |
105 |
} |
106 |
|
107 |
/** |
108 |
* Get the containing Spring {@link WebApplicationContext}. |
109 |
* This only works after the servlet has been initialized (via {@link #init init()}). |
110 |
* |
111 |
* @throws ServletException if the operation fails |
112 |
*/ |
113 |
protected final WebApplicationContext getWebApplicationContext() throws ServletException { |
114 |
if (this.webApplicationContext == null) |
115 |
throw new ServletException("can't retrieve WebApplicationContext before init() is invoked"); |
116 |
return this.webApplicationContext; |
117 |
} |
118 |
|
119 |
/** |
120 |
* Get the {@link AutowireCapableBeanFactory} associated with the containing Spring {@link WebApplicationContext}. |
121 |
* This only works after the servlet has been initialized (via {@link #init init()}). |
122 |
* |
123 |
* @throws ServletException if the operation fails |
124 |
*/ |
125 |
protected final AutowireCapableBeanFactory getAutowireCapableBeanFactory() throws ServletException { |
126 |
try { |
127 |
return getWebApplicationContext().getAutowireCapableBeanFactory(); |
128 |
} catch (IllegalStateException e) { |
129 |
throw new ServletException("containing context " + getWebApplicationContext() + " is not autowire-capable", e); |
130 |
} |
131 |
} |
132 |
|
133 |
/** |
134 |
* Create and configure a new instance of the configured application class. |
135 |
* |
136 |
* <p> |
137 |
* The implementation in {@link AutowiringApplicationServlet} delegates to |
138 |
* {@link #getAutowireCapableBeanFactory getAutowireCapableBeanFactory()}, then invokes |
139 |
* {@link AutowireCapableBeanFactory#createBean AutowireCapableBeanFactory.createBean()} |
140 |
* using the configured {@link Application} class. |
141 |
* </p> |
142 |
* |
143 |
* @param request the triggering {@link HttpServletRequest} |
144 |
* @throws ServletException if creation or autowiring fails |
145 |
*/ |
146 |
@Override |
147 |
protected Application getNewApplication(HttpServletRequest request) throws ServletException { |
148 |
Class<? extends Application> cl = getApplicationClass(); |
149 |
AutowireCapableBeanFactory beanFactory = getAutowireCapableBeanFactory(); |
150 |
try { |
151 |
return beanFactory.createBean(cl); |
152 |
} catch (BeansException e) { |
153 |
throw new ServletException("failed to create new instance of " + cl, e); |
154 |
} |
155 |
} |
156 |
} |