19
19
import java .util .Arrays ;
20
20
import java .util .LinkedHashSet ;
21
21
import java .util .List ;
22
+ import java .util .Map ;
22
23
import java .util .Set ;
23
24
import javax .servlet .ServletContext ;
24
25
import javax .websocket .DeploymentException ;
27
28
import javax .websocket .server .ServerEndpointConfig ;
28
29
29
30
import org .springframework .beans .factory .InitializingBean ;
30
- import org .springframework .beans .factory .config . BeanPostProcessor ;
31
+ import org .springframework .beans .factory .SmartInitializingSingleton ;
31
32
import org .springframework .context .ApplicationContext ;
32
33
import org .springframework .util .Assert ;
33
34
import org .springframework .web .context .support .WebApplicationObjectSupport ;
41
42
*
42
43
* <p>When this class is used, by declaring it in Spring configuration, it should be
43
44
* possible to turn off a Servlet container's scan for WebSocket endpoints. This can be
44
- * done with the help of the {@code <absolute-ordering>} element in web.xml.
45
+ * done with the help of the {@code <absolute-ordering>} element in {@code web.xml} .
45
46
*
46
47
* @author Rossen Stoyanchev
47
48
* @author Juergen Hoeller
50
51
* @see SpringConfigurator
51
52
* @see ServletServerContainerFactoryBean
52
53
*/
53
- public class ServerEndpointExporter extends WebApplicationObjectSupport implements BeanPostProcessor , InitializingBean {
54
-
55
- private ServerContainer serverContainer ;
54
+ public class ServerEndpointExporter extends WebApplicationObjectSupport
55
+ implements InitializingBean , SmartInitializingSingleton {
56
56
57
57
private List <Class <?>> annotatedEndpointClasses ;
58
58
59
- private Set <Class <?>> annotatedEndpointBeanTypes ;
59
+ private ServerContainer serverContainer ;
60
+
60
61
62
+ /**
63
+ * Explicitly list annotated endpoint types that should be registered on startup. This
64
+ * can be done if you wish to turn off a Servlet container's scan for endpoints, which
65
+ * goes through all 3rd party jars in the, and rely on Spring configuration instead.
66
+ * @param annotatedEndpointClasses {@link ServerEndpoint}-annotated types
67
+ */
68
+ public void setAnnotatedEndpointClasses (Class <?>... annotatedEndpointClasses ) {
69
+ this .annotatedEndpointClasses = Arrays .asList (annotatedEndpointClasses );
70
+ }
61
71
62
72
/**
63
73
* Set the JSR-356 {@link ServerContainer} to use for endpoint registration.
64
74
* If not set, the container is going to be retrieved via the {@code ServletContext}.
65
- * @since 4.1
66
75
*/
67
76
public void setServerContainer (ServerContainer serverContainer ) {
68
77
this .serverContainer = serverContainer ;
@@ -75,33 +84,6 @@ protected ServerContainer getServerContainer() {
75
84
return this .serverContainer ;
76
85
}
77
86
78
- /**
79
- * Explicitly list annotated endpoint types that should be registered on startup. This
80
- * can be done if you wish to turn off a Servlet container's scan for endpoints, which
81
- * goes through all 3rd party jars in the, and rely on Spring configuration instead.
82
- * @param annotatedEndpointClasses {@link ServerEndpoint}-annotated types
83
- */
84
- public void setAnnotatedEndpointClasses (Class <?>... annotatedEndpointClasses ) {
85
- this .annotatedEndpointClasses = Arrays .asList (annotatedEndpointClasses );
86
- }
87
-
88
- @ Override
89
- protected void initApplicationContext (ApplicationContext context ) {
90
- // Initializes ServletContext given a WebApplicationContext
91
- super .initApplicationContext (context );
92
-
93
- // Retrieve beans which are annotated with @ServerEndpoint
94
- this .annotatedEndpointBeanTypes = new LinkedHashSet <Class <?>>();
95
- String [] beanNames = context .getBeanNamesForAnnotation (ServerEndpoint .class );
96
- for (String beanName : beanNames ) {
97
- Class <?> beanType = context .getType (beanName );
98
- if (logger .isInfoEnabled ()) {
99
- logger .info ("Detected @ServerEndpoint bean '" + beanName + "', registering it as an endpoint by type" );
100
- }
101
- this .annotatedEndpointBeanTypes .add (beanType );
102
- }
103
- }
104
-
105
87
@ Override
106
88
protected void initServletContext (ServletContext servletContext ) {
107
89
if (this .serverContainer == null ) {
@@ -110,64 +92,76 @@ protected void initServletContext(ServletContext servletContext) {
110
92
}
111
93
}
112
94
95
+ @ Override
96
+ protected boolean isContextRequired () {
97
+ return false ;
98
+ }
113
99
114
100
@ Override
115
101
public void afterPropertiesSet () {
116
102
Assert .state (getServerContainer () != null , "javax.websocket.server.ServerContainer not available" );
103
+ }
104
+
105
+ @ Override
106
+ public void afterSingletonsInstantiated () {
117
107
registerEndpoints ();
118
108
}
119
109
110
+
120
111
/**
121
- * Actually register the endpoints. Called by {@link #afterPropertiesSet()}.
122
- * @since 4.1
112
+ * Actually register the endpoints. Called by {@link #afterSingletonsInstantiated()}.
123
113
*/
124
114
protected void registerEndpoints () {
125
115
Set <Class <?>> endpointClasses = new LinkedHashSet <Class <?>>();
126
116
if (this .annotatedEndpointClasses != null ) {
127
117
endpointClasses .addAll (this .annotatedEndpointClasses );
128
118
}
129
- if (this .annotatedEndpointBeanTypes != null ) {
130
- endpointClasses .addAll (this .annotatedEndpointBeanTypes );
119
+
120
+ ApplicationContext context = getApplicationContext ();
121
+ if (context != null ) {
122
+ String [] endpointNames = context .getBeanNamesForAnnotation (ServerEndpoint .class );
123
+ for (String beanName : endpointNames ) {
124
+ Class <?> beanType = context .getType (beanName );
125
+ endpointClasses .add (beanType );
126
+ }
131
127
}
128
+
132
129
for (Class <?> endpointClass : endpointClasses ) {
133
130
registerEndpoint (endpointClass );
134
131
}
132
+
133
+ if (context != null ) {
134
+ Map <String , ServerEndpointConfig > endpointConfigMap = context .getBeansOfType (ServerEndpointConfig .class );
135
+ for (Map .Entry <String , ServerEndpointConfig > configEntry : endpointConfigMap .entrySet ()) {
136
+ String beanName = configEntry .getKey ();
137
+ ServerEndpointConfig endpointConfig = configEntry .getValue ();
138
+ registerEndpoint (endpointConfig );
139
+ }
140
+ }
135
141
}
136
142
137
143
private void registerEndpoint (Class <?> endpointClass ) {
138
144
try {
139
145
if (logger .isInfoEnabled ()) {
140
- logger .info ("Registering @ServerEndpoint type : " + endpointClass );
146
+ logger .info ("Registering @ServerEndpoint class : " + endpointClass );
141
147
}
142
148
getServerContainer ().addEndpoint (endpointClass );
143
149
}
144
150
catch (DeploymentException ex ) {
145
- throw new IllegalStateException ("Failed to register @ServerEndpoint type " + endpointClass , ex );
151
+ throw new IllegalStateException ("Failed to register @ServerEndpoint class: " + endpointClass , ex );
146
152
}
147
153
}
148
154
149
-
150
- @ Override
151
- public Object postProcessBeforeInitialization (Object bean , String beanName ) {
152
- return bean ;
153
- }
154
-
155
- @ Override
156
- public Object postProcessAfterInitialization (Object bean , String beanName ) {
157
- if (bean instanceof ServerEndpointConfig ) {
158
- ServerEndpointConfig endpointConfig = (ServerEndpointConfig ) bean ;
159
- try {
160
- if (logger .isInfoEnabled ()) {
161
- logger .info ("Registering bean '" + beanName +
162
- "' as javax.websocket.Endpoint under path " + endpointConfig .getPath ());
163
- }
164
- getServerContainer ().addEndpoint (endpointConfig );
165
- }
166
- catch (DeploymentException ex ) {
167
- throw new IllegalStateException ("Failed to deploy Endpoint bean with name '" + bean + "'" , ex );
155
+ private void registerEndpoint (ServerEndpointConfig endpointConfig ) {
156
+ try {
157
+ if (logger .isInfoEnabled ()) {
158
+ logger .info ("Registering ServerEndpointConfig: " + endpointConfig );
168
159
}
160
+ getServerContainer ().addEndpoint (endpointConfig );
161
+ }
162
+ catch (DeploymentException ex ) {
163
+ throw new IllegalStateException ("Failed to register ServerEndpointConfig: " + endpointConfig , ex );
169
164
}
170
- return bean ;
171
165
}
172
166
173
167
}
0 commit comments