3737import org .springframework .web .reactive .socket .server .RequestUpgradeStrategy ;
3838import org .springframework .web .server .ServerWebExchange ;
3939
40+
4041/**
4142 * A {@link RequestUpgradeStrategy} for use with Jetty.
4243 *
4546 */
4647public class JettyRequestUpgradeStrategy implements RequestUpgradeStrategy , Lifecycle {
4748
48- private static final ThreadLocal <JettyWebSocketHandlerAdapter > wsContainerHolder =
49- new NamedThreadLocal <>("Jetty WebSocketHandler Adapter " );
49+ private static final ThreadLocal <JettyWebSocketHandlerAdapter > adapterHolder =
50+ new NamedThreadLocal <>("JettyWebSocketHandlerAdapter " );
5051
5152
5253 private WebSocketServerFactory factory ;
5354
5455 private ServletContext servletContext ;
5556
56- private volatile boolean running = false ;
57+ private boolean running = false ;
58+
59+ private final Object lifecycleMonitor = new Object ();
5760
5861
5962 @ Override
6063 public void start () {
61- if (!isRunning () && this .servletContext != null ) {
62- this .running = true ;
63- try {
64- this .factory = new WebSocketServerFactory (this .servletContext );
65- this .factory .setCreator ((request , response ) -> {
66- JettyWebSocketHandlerAdapter adapter = wsContainerHolder .get ();
67- Assert .state (adapter != null , "Expected JettyWebSocketHandlerAdapter" );
68- return adapter ;
69- });
70- this .factory .start ();
71- }
72- catch (Exception ex ) {
73- throw new IllegalStateException ("Unable to start Jetty WebSocketServerFactory" , ex );
64+ synchronized (this .lifecycleMonitor ) {
65+ if (!isRunning () && this .servletContext != null ) {
66+ this .running = true ;
67+ try {
68+ this .factory = new WebSocketServerFactory (this .servletContext );
69+ this .factory .setCreator ((request , response ) -> adapterHolder .get ());
70+ this .factory .start ();
71+ }
72+ catch (Exception ex ) {
73+ throw new IllegalStateException ("Unable to start WebSocketServerFactory" , ex );
74+ }
7475 }
7576 }
7677 }
7778
7879 @ Override
7980 public void stop () {
80- if (isRunning ()) {
81- this .running = false ;
82- try {
83- this .factory .stop ();
84- }
85- catch (Exception ex ) {
86- throw new IllegalStateException ("Unable to stop Jetty WebSocketServerFactory" , ex );
81+ synchronized (this .lifecycleMonitor ) {
82+ if (isRunning ()) {
83+ try {
84+ this .factory .stop ();
85+ }
86+ catch (Exception ex ) {
87+ throw new IllegalStateException ("Failed to stop WebSocketServerFactory" , ex );
88+ }
89+ finally {
90+ this .running = false ;
91+ }
8792 }
8893 }
8994 }
9095
9196 @ Override
9297 public boolean isRunning () {
93- return this .running ;
98+ synchronized (this .lifecycleMonitor ) {
99+ return this .running ;
100+ }
94101 }
95102
96103 @ Override
@@ -103,25 +110,20 @@ public Mono<Void> upgrade(ServerWebExchange exchange, WebSocketHandler handler)
103110 HttpServletRequest servletRequest = getHttpServletRequest (request );
104111 HttpServletResponse servletResponse = getHttpServletResponse (response );
105112
106- if (this .servletContext == null ) {
107- this .servletContext = servletRequest .getServletContext ();
108- this .servletContext .setAttribute (DecoratedObjectFactory .ATTR , new DecoratedObjectFactory ());
109- }
110-
111- try {
112- start ();
113+ startLazily (servletRequest );
113114
114- Assert . isTrue ( this .factory .isUpgradeRequest (
115- servletRequest , servletResponse ) , "Not a WebSocket handshake" );
115+ boolean isUpgrade = this .factory .isUpgradeRequest (servletRequest , servletResponse );
116+ Assert . isTrue ( isUpgrade , "Not a WebSocket handshake" );
116117
117- wsContainerHolder .set (adapter );
118+ try {
119+ adapterHolder .set (adapter );
118120 this .factory .acceptWebSocket (servletRequest , servletResponse );
119121 }
120122 catch (IOException ex ) {
121123 return Mono .error (ex );
122124 }
123125 finally {
124- wsContainerHolder .remove ();
126+ adapterHolder .remove ();
125127 }
126128
127129 return Mono .empty ();
@@ -137,4 +139,17 @@ private HttpServletResponse getHttpServletResponse(ServerHttpResponse response)
137139 return ((ServletServerHttpResponse ) response ).getServletResponse ();
138140 }
139141
142+ private void startLazily (HttpServletRequest request ) {
143+ if (this .servletContext != null ) {
144+ return ;
145+ }
146+ synchronized (this .lifecycleMonitor ) {
147+ if (this .servletContext == null ) {
148+ this .servletContext = request .getServletContext ();
149+ this .servletContext .setAttribute (DecoratedObjectFactory .ATTR , new DecoratedObjectFactory ());
150+ start ();
151+ }
152+ }
153+ }
154+
140155}
0 commit comments