1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.springframework.web.servlet;
18
19 import java.io.IOException;
20 import java.security.Principal;
21 import java.util.ArrayList;
22 import java.util.concurrent.Callable;
23 import javax.servlet.ServletContext;
24 import javax.servlet.ServletException;
25 import javax.servlet.http.HttpServletRequest;
26 import javax.servlet.http.HttpServletResponse;
27 import javax.servlet.http.HttpServletResponseWrapper;
28
29 import org.springframework.beans.BeanUtils;
30 import org.springframework.context.ApplicationContext;
31 import org.springframework.context.ApplicationContextAware;
32 import org.springframework.context.ApplicationContextException;
33 import org.springframework.context.ApplicationContextInitializer;
34 import org.springframework.context.ApplicationListener;
35 import org.springframework.context.ConfigurableApplicationContext;
36 import org.springframework.context.event.ContextRefreshedEvent;
37 import org.springframework.context.event.SourceFilteringListener;
38 import org.springframework.context.i18n.LocaleContext;
39 import org.springframework.context.i18n.LocaleContextHolder;
40 import org.springframework.context.i18n.SimpleLocaleContext;
41 import org.springframework.core.GenericTypeResolver;
42 import org.springframework.core.annotation.AnnotationAwareOrderComparator;
43 import org.springframework.core.env.ConfigurableEnvironment;
44 import org.springframework.util.Assert;
45 import org.springframework.util.ClassUtils;
46 import org.springframework.util.ObjectUtils;
47 import org.springframework.util.StringUtils;
48 import org.springframework.web.bind.annotation.RequestMethod;
49 import org.springframework.web.context.ConfigurableWebApplicationContext;
50 import org.springframework.web.context.ConfigurableWebEnvironment;
51 import org.springframework.web.context.ContextLoader;
52 import org.springframework.web.context.WebApplicationContext;
53 import org.springframework.web.context.request.NativeWebRequest;
54 import org.springframework.web.context.request.RequestAttributes;
55 import org.springframework.web.context.request.RequestContextHolder;
56 import org.springframework.web.context.request.ServletRequestAttributes;
57 import org.springframework.web.context.request.async.CallableProcessingInterceptorAdapter;
58 import org.springframework.web.context.request.async.WebAsyncManager;
59 import org.springframework.web.context.request.async.WebAsyncUtils;
60 import org.springframework.web.context.support.ServletRequestHandledEvent;
61 import org.springframework.web.context.support.WebApplicationContextUtils;
62 import org.springframework.web.context.support.XmlWebApplicationContext;
63 import org.springframework.web.util.NestedServletException;
64 import org.springframework.web.util.WebUtils;
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135 @SuppressWarnings("serial")
136 public abstract class FrameworkServlet extends HttpServletBean implements ApplicationContextAware {
137
138
139
140
141
142
143 public static final String DEFAULT_NAMESPACE_SUFFIX = "-servlet";
144
145
146
147
148
149 public static final Class<?> DEFAULT_CONTEXT_CLASS = XmlWebApplicationContext.class;
150
151
152
153
154
155 public static final String SERVLET_CONTEXT_PREFIX = FrameworkServlet.class.getName() + ".CONTEXT.";
156
157
158
159
160
161 private static final String INIT_PARAM_DELIMITERS = ",; \t\n";
162
163
164
165 private static final boolean responseGetStatusAvailable =
166 ClassUtils.hasMethod(HttpServletResponse.class, "getStatus");
167
168
169
170 private String contextAttribute;
171
172
173 private Class<?> contextClass = DEFAULT_CONTEXT_CLASS;
174
175
176 private String contextId;
177
178
179 private String namespace;
180
181
182 private String contextConfigLocation;
183
184
185 private final ArrayList<ApplicationContextInitializer<ConfigurableApplicationContext>> contextInitializers =
186 new ArrayList<ApplicationContextInitializer<ConfigurableApplicationContext>>();
187
188
189 private String contextInitializerClasses;
190
191
192 private boolean publishContext = true;
193
194
195 private boolean publishEvents = true;
196
197
198 private boolean threadContextInheritable = false;
199
200
201 private boolean dispatchOptionsRequest = false;
202
203
204 private boolean dispatchTraceRequest = false;
205
206
207 private WebApplicationContext webApplicationContext;
208
209
210 private boolean webApplicationContextInjected = false;
211
212
213 private boolean refreshEventReceived = false;
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233 public FrameworkServlet() {
234 }
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276 public FrameworkServlet(WebApplicationContext webApplicationContext) {
277 this.webApplicationContext = webApplicationContext;
278 }
279
280
281
282
283
284
285 public void setContextAttribute(String contextAttribute) {
286 this.contextAttribute = contextAttribute;
287 }
288
289
290
291
292
293 public String getContextAttribute() {
294 return this.contextAttribute;
295 }
296
297
298
299
300
301
302
303
304
305
306 public void setContextClass(Class<?> contextClass) {
307 this.contextClass = contextClass;
308 }
309
310
311
312
313 public Class<?> getContextClass() {
314 return this.contextClass;
315 }
316
317
318
319
320
321 public void setContextId(String contextId) {
322 this.contextId = contextId;
323 }
324
325
326
327
328 public String getContextId() {
329 return this.contextId;
330 }
331
332
333
334
335
336 public void setNamespace(String namespace) {
337 this.namespace = namespace;
338 }
339
340
341
342
343
344 public String getNamespace() {
345 return (this.namespace != null ? this.namespace : getServletName() + DEFAULT_NAMESPACE_SUFFIX);
346 }
347
348
349
350
351
352
353 public void setContextConfigLocation(String contextConfigLocation) {
354 this.contextConfigLocation = contextConfigLocation;
355 }
356
357
358
359
360 public String getContextConfigLocation() {
361 return this.contextConfigLocation;
362 }
363
364
365
366
367
368
369
370 @SuppressWarnings("unchecked")
371 public void setContextInitializers(ApplicationContextInitializer<? extends ConfigurableApplicationContext>... contextInitializers) {
372 for (ApplicationContextInitializer<? extends ConfigurableApplicationContext> initializer : contextInitializers) {
373 this.contextInitializers.add((ApplicationContextInitializer<ConfigurableApplicationContext>) initializer);
374 }
375 }
376
377
378
379
380
381
382
383 public void setContextInitializerClasses(String contextInitializerClasses) {
384 this.contextInitializerClasses = contextInitializerClasses;
385 }
386
387
388
389
390
391
392
393 public void setPublishContext(boolean publishContext) {
394 this.publishContext = publishContext;
395 }
396
397
398
399
400
401
402
403 public void setPublishEvents(boolean publishEvents) {
404 this.publishEvents = publishEvents;
405 }
406
407
408
409
410
411
412
413
414
415
416
417
418
419 public void setThreadContextInheritable(boolean threadContextInheritable) {
420 this.threadContextInheritable = threadContextInheritable;
421 }
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437 public void setDispatchOptionsRequest(boolean dispatchOptionsRequest) {
438 this.dispatchOptionsRequest = dispatchOptionsRequest;
439 }
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454 public void setDispatchTraceRequest(boolean dispatchTraceRequest) {
455 this.dispatchTraceRequest = dispatchTraceRequest;
456 }
457
458
459
460
461
462
463
464
465
466
467 @Override
468 public void setApplicationContext(ApplicationContext applicationContext) {
469 if (this.webApplicationContext == null && applicationContext instanceof WebApplicationContext) {
470 this.webApplicationContext = (WebApplicationContext) applicationContext;
471 this.webApplicationContextInjected = true;
472 }
473 }
474
475
476
477
478
479
480 @Override
481 protected final void initServletBean() throws ServletException {
482 getServletContext().log("Initializing Spring FrameworkServlet '" + getServletName() + "'");
483 if (this.logger.isInfoEnabled()) {
484 this.logger.info("FrameworkServlet '" + getServletName() + "': initialization started");
485 }
486 long startTime = System.currentTimeMillis();
487
488 try {
489 this.webApplicationContext = initWebApplicationContext();
490 initFrameworkServlet();
491 }
492 catch (ServletException ex) {
493 this.logger.error("Context initialization failed", ex);
494 throw ex;
495 }
496 catch (RuntimeException ex) {
497 this.logger.error("Context initialization failed", ex);
498 throw ex;
499 }
500
501 if (this.logger.isInfoEnabled()) {
502 long elapsedTime = System.currentTimeMillis() - startTime;
503 this.logger.info("FrameworkServlet '" + getServletName() + "': initialization completed in " +
504 elapsedTime + " ms");
505 }
506 }
507
508
509
510
511
512
513
514
515
516
517 protected WebApplicationContext initWebApplicationContext() {
518 WebApplicationContext rootContext =
519 WebApplicationContextUtils.getWebApplicationContext(getServletContext());
520 WebApplicationContext wac = null;
521
522 if (this.webApplicationContext != null) {
523
524 wac = this.webApplicationContext;
525 if (wac instanceof ConfigurableWebApplicationContext) {
526 ConfigurableWebApplicationContext cwac = (ConfigurableWebApplicationContext) wac;
527 if (!cwac.isActive()) {
528
529
530 if (cwac.getParent() == null) {
531
532
533 cwac.setParent(rootContext);
534 }
535 configureAndRefreshWebApplicationContext(cwac);
536 }
537 }
538 }
539 if (wac == null) {
540
541
542
543
544 wac = findWebApplicationContext();
545 }
546 if (wac == null) {
547
548 wac = createWebApplicationContext(rootContext);
549 }
550
551 if (!this.refreshEventReceived) {
552
553
554
555 onRefresh(wac);
556 }
557
558 if (this.publishContext) {
559
560 String attrName = getServletContextAttributeName();
561 getServletContext().setAttribute(attrName, wac);
562 if (this.logger.isDebugEnabled()) {
563 this.logger.debug("Published WebApplicationContext of servlet '" + getServletName() +
564 "' as ServletContext attribute with name [" + attrName + "]");
565 }
566 }
567
568 return wac;
569 }
570
571
572
573
574
575
576
577
578
579
580
581 protected WebApplicationContext findWebApplicationContext() {
582 String attrName = getContextAttribute();
583 if (attrName == null) {
584 return null;
585 }
586 WebApplicationContext wac =
587 WebApplicationContextUtils.getWebApplicationContext(getServletContext(), attrName);
588 if (wac == null) {
589 throw new IllegalStateException("No WebApplicationContext found: initializer not registered?");
590 }
591 return wac;
592 }
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609 protected WebApplicationContext createWebApplicationContext(ApplicationContext parent) {
610 Class<?> contextClass = getContextClass();
611 if (this.logger.isDebugEnabled()) {
612 this.logger.debug("Servlet with name '" + getServletName() +
613 "' will try to create custom WebApplicationContext context of class '" +
614 contextClass.getName() + "'" + ", using parent context [" + parent + "]");
615 }
616 if (!ConfigurableWebApplicationContext.class.isAssignableFrom(contextClass)) {
617 throw new ApplicationContextException(
618 "Fatal initialization error in servlet with name '" + getServletName() +
619 "': custom WebApplicationContext class [" + contextClass.getName() +
620 "] is not of type ConfigurableWebApplicationContext");
621 }
622 ConfigurableWebApplicationContext wac =
623 (ConfigurableWebApplicationContext) BeanUtils.instantiateClass(contextClass);
624
625 wac.setEnvironment(getEnvironment());
626 wac.setParent(parent);
627 wac.setConfigLocation(getContextConfigLocation());
628
629 configureAndRefreshWebApplicationContext(wac);
630
631 return wac;
632 }
633
634 protected void configureAndRefreshWebApplicationContext(ConfigurableWebApplicationContext wac) {
635 if (ObjectUtils.identityToString(wac).equals(wac.getId())) {
636
637
638 if (this.contextId != null) {
639 wac.setId(this.contextId);
640 }
641 else {
642
643 wac.setId(ConfigurableWebApplicationContext.APPLICATION_CONTEXT_ID_PREFIX +
644 ObjectUtils.getDisplayString(getServletContext().getContextPath()) + "/" + getServletName());
645 }
646 }
647
648 wac.setServletContext(getServletContext());
649 wac.setServletConfig(getServletConfig());
650 wac.setNamespace(getNamespace());
651 wac.addApplicationListener(new SourceFilteringListener(wac, new ContextRefreshListener()));
652
653
654
655
656 ConfigurableEnvironment env = wac.getEnvironment();
657 if (env instanceof ConfigurableWebEnvironment) {
658 ((ConfigurableWebEnvironment) env).initPropertySources(getServletContext(), getServletConfig());
659 }
660
661 postProcessWebApplicationContext(wac);
662 applyInitializers(wac);
663 wac.refresh();
664 }
665
666
667
668
669
670
671
672
673
674
675
676 protected WebApplicationContext createWebApplicationContext(WebApplicationContext parent) {
677 return createWebApplicationContext((ApplicationContext) parent);
678 }
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694 protected void postProcessWebApplicationContext(ConfigurableWebApplicationContext wac) {
695 }
696
697
698
699
700
701
702
703
704
705
706
707
708
709 protected void applyInitializers(ConfigurableApplicationContext wac) {
710 String globalClassNames = getServletContext().getInitParameter(ContextLoader.GLOBAL_INITIALIZER_CLASSES_PARAM);
711 if (globalClassNames != null) {
712 for (String className : StringUtils.tokenizeToStringArray(globalClassNames, INIT_PARAM_DELIMITERS)) {
713 this.contextInitializers.add(loadInitializer(className, wac));
714 }
715 }
716
717 if (this.contextInitializerClasses != null) {
718 for (String className : StringUtils.tokenizeToStringArray(this.contextInitializerClasses, INIT_PARAM_DELIMITERS)) {
719 this.contextInitializers.add(loadInitializer(className, wac));
720 }
721 }
722
723 AnnotationAwareOrderComparator.sort(this.contextInitializers);
724 for (ApplicationContextInitializer<ConfigurableApplicationContext> initializer : this.contextInitializers) {
725 initializer.initialize(wac);
726 }
727 }
728
729 @SuppressWarnings("unchecked")
730 private ApplicationContextInitializer<ConfigurableApplicationContext> loadInitializer(
731 String className, ConfigurableApplicationContext wac) {
732 try {
733 Class<?> initializerClass = ClassUtils.forName(className, wac.getClassLoader());
734 Class<?> initializerContextClass =
735 GenericTypeResolver.resolveTypeArgument(initializerClass, ApplicationContextInitializer.class);
736 if (initializerContextClass != null) {
737 Assert.isAssignable(initializerContextClass, wac.getClass(), String.format(
738 "Could not add context initializer [%s] since its generic parameter [%s] " +
739 "is not assignable from the type of application context used by this " +
740 "framework servlet [%s]: ", initializerClass.getName(), initializerContextClass.getName(),
741 wac.getClass().getName()));
742 }
743 return BeanUtils.instantiateClass(initializerClass, ApplicationContextInitializer.class);
744 }
745 catch (Exception ex) {
746 throw new IllegalArgumentException(String.format("Could not instantiate class [%s] specified " +
747 "via 'contextInitializerClasses' init-param", className), ex);
748 }
749 }
750
751
752
753
754
755
756
757
758 public String getServletContextAttributeName() {
759 return SERVLET_CONTEXT_PREFIX + getServletName();
760 }
761
762
763
764
765 public final WebApplicationContext getWebApplicationContext() {
766 return this.webApplicationContext;
767 }
768
769
770
771
772
773
774
775
776 protected void initFrameworkServlet() throws ServletException {
777 }
778
779
780
781
782
783
784
785 public void refresh() {
786 WebApplicationContext wac = getWebApplicationContext();
787 if (!(wac instanceof ConfigurableApplicationContext)) {
788 throw new IllegalStateException("WebApplicationContext does not support refresh: " + wac);
789 }
790 ((ConfigurableApplicationContext) wac).refresh();
791 }
792
793
794
795
796
797
798
799 public void onApplicationEvent(ContextRefreshedEvent event) {
800 this.refreshEventReceived = true;
801 onRefresh(event.getApplicationContext());
802 }
803
804
805
806
807
808
809
810
811 protected void onRefresh(ApplicationContext context) {
812
813 }
814
815
816
817
818
819 @Override
820 public void destroy() {
821 getServletContext().log("Destroying Spring FrameworkServlet '" + getServletName() + "'");
822
823 if (this.webApplicationContext instanceof ConfigurableApplicationContext && !this.webApplicationContextInjected) {
824 ((ConfigurableApplicationContext) this.webApplicationContext).close();
825 }
826 }
827
828
829
830
831
832
833 @Override
834 protected void service(HttpServletRequest request, HttpServletResponse response)
835 throws ServletException, IOException {
836
837 String method = request.getMethod();
838 if (method.equalsIgnoreCase(RequestMethod.PATCH.name())) {
839 processRequest(request, response);
840 }
841 else {
842 super.service(request, response);
843 }
844 }
845
846
847
848
849
850
851
852
853 @Override
854 protected final void doGet(HttpServletRequest request, HttpServletResponse response)
855 throws ServletException, IOException {
856
857 processRequest(request, response);
858 }
859
860
861
862
863
864 @Override
865 protected final void doPost(HttpServletRequest request, HttpServletResponse response)
866 throws ServletException, IOException {
867
868 processRequest(request, response);
869 }
870
871
872
873
874
875 @Override
876 protected final void doPut(HttpServletRequest request, HttpServletResponse response)
877 throws ServletException, IOException {
878
879 processRequest(request, response);
880 }
881
882
883
884
885
886 @Override
887 protected final void doDelete(HttpServletRequest request, HttpServletResponse response)
888 throws ServletException, IOException {
889
890 processRequest(request, response);
891 }
892
893
894
895
896
897
898
899 @Override
900 protected void doOptions(HttpServletRequest request, HttpServletResponse response)
901 throws ServletException, IOException {
902
903 if (this.dispatchOptionsRequest) {
904 processRequest(request, response);
905 if (response.containsHeader("Allow")) {
906
907 return;
908 }
909 }
910
911
912
913 super.doOptions(request, new HttpServletResponseWrapper(response) {
914 @Override
915 public void setHeader(String name, String value) {
916 if ("Allow".equals(name)) {
917 value = (StringUtils.hasLength(value) ? value + ", " : "") + RequestMethod.PATCH.name();
918 }
919 super.setHeader(name, value);
920 }
921 });
922 }
923
924
925
926
927
928
929 @Override
930 protected void doTrace(HttpServletRequest request, HttpServletResponse response)
931 throws ServletException, IOException {
932
933 if (this.dispatchTraceRequest) {
934 processRequest(request, response);
935 if ("message/http".equals(response.getContentType())) {
936
937 return;
938 }
939 }
940 super.doTrace(request, response);
941 }
942
943
944
945
946
947
948 protected final void processRequest(HttpServletRequest request, HttpServletResponse response)
949 throws ServletException, IOException {
950
951 long startTime = System.currentTimeMillis();
952 Throwable failureCause = null;
953
954 LocaleContext previousLocaleContext = LocaleContextHolder.getLocaleContext();
955 LocaleContext localeContext = buildLocaleContext(request);
956
957 RequestAttributes previousAttributes = RequestContextHolder.getRequestAttributes();
958 ServletRequestAttributes requestAttributes = buildRequestAttributes(request, response, previousAttributes);
959
960 WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);
961 asyncManager.registerCallableInterceptor(FrameworkServlet.class.getName(), new RequestBindingInterceptor());
962
963 initContextHolders(request, localeContext, requestAttributes);
964
965 try {
966 doService(request, response);
967 }
968 catch (ServletException ex) {
969 failureCause = ex;
970 throw ex;
971 }
972 catch (IOException ex) {
973 failureCause = ex;
974 throw ex;
975 }
976 catch (Throwable ex) {
977 failureCause = ex;
978 throw new NestedServletException("Request processing failed", ex);
979 }
980
981 finally {
982 resetContextHolders(request, previousLocaleContext, previousAttributes);
983 if (requestAttributes != null) {
984 requestAttributes.requestCompleted();
985 }
986
987 if (logger.isDebugEnabled()) {
988 if (failureCause != null) {
989 this.logger.debug("Could not complete request", failureCause);
990 }
991 else {
992 if (asyncManager.isConcurrentHandlingStarted()) {
993 logger.debug("Leaving response open for concurrent processing");
994 }
995 else {
996 this.logger.debug("Successfully completed request");
997 }
998 }
999 }
1000
1001 publishRequestHandledEvent(request, response, startTime, failureCause);
1002 }
1003 }
1004
1005
1006
1007
1008
1009
1010
1011
1012 protected LocaleContext buildLocaleContext(HttpServletRequest request) {
1013 return new SimpleLocaleContext(request.getLocale());
1014 }
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027 protected ServletRequestAttributes buildRequestAttributes(
1028 HttpServletRequest request, HttpServletResponse response, RequestAttributes previousAttributes) {
1029
1030 if (previousAttributes == null || previousAttributes instanceof ServletRequestAttributes) {
1031 return new ServletRequestAttributes(request, response);
1032 }
1033 else {
1034 return null;
1035 }
1036 }
1037
1038 private void initContextHolders(
1039 HttpServletRequest request, LocaleContext localeContext, RequestAttributes requestAttributes) {
1040
1041 if (localeContext != null) {
1042 LocaleContextHolder.setLocaleContext(localeContext, this.threadContextInheritable);
1043 }
1044 if (requestAttributes != null) {
1045 RequestContextHolder.setRequestAttributes(requestAttributes, this.threadContextInheritable);
1046 }
1047 if (logger.isTraceEnabled()) {
1048 logger.trace("Bound request context to thread: " + request);
1049 }
1050 }
1051
1052 private void resetContextHolders(HttpServletRequest request,
1053 LocaleContext prevLocaleContext, RequestAttributes previousAttributes) {
1054
1055 LocaleContextHolder.setLocaleContext(prevLocaleContext, this.threadContextInheritable);
1056 RequestContextHolder.setRequestAttributes(previousAttributes, this.threadContextInheritable);
1057 if (logger.isTraceEnabled()) {
1058 logger.trace("Cleared thread-bound request context: " + request);
1059 }
1060 }
1061
1062 private void publishRequestHandledEvent(
1063 HttpServletRequest request, HttpServletResponse response, long startTime, Throwable failureCause) {
1064
1065 if (this.publishEvents) {
1066
1067 long processingTime = System.currentTimeMillis() - startTime;
1068 int statusCode = (responseGetStatusAvailable ? response.getStatus() : -1);
1069 this.webApplicationContext.publishEvent(
1070 new ServletRequestHandledEvent(this,
1071 request.getRequestURI(), request.getRemoteAddr(),
1072 request.getMethod(), getServletConfig().getServletName(),
1073 WebUtils.getSessionId(request), getUsernameForRequest(request),
1074 processingTime, failureCause, statusCode));
1075 }
1076 }
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086 protected String getUsernameForRequest(HttpServletRequest request) {
1087 Principal userPrincipal = request.getUserPrincipal();
1088 return (userPrincipal != null ? userPrincipal.getName() : null);
1089 }
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105 protected abstract void doService(HttpServletRequest request, HttpServletResponse response)
1106 throws Exception;
1107
1108
1109
1110
1111
1112
1113 private class ContextRefreshListener implements ApplicationListener<ContextRefreshedEvent> {
1114
1115 @Override
1116 public void onApplicationEvent(ContextRefreshedEvent event) {
1117 FrameworkServlet.this.onApplicationEvent(event);
1118 }
1119 }
1120
1121
1122
1123
1124
1125
1126 private class RequestBindingInterceptor extends CallableProcessingInterceptorAdapter {
1127
1128 @Override
1129 public <T> void preProcess(NativeWebRequest webRequest, Callable<T> task) {
1130 HttpServletRequest request = webRequest.getNativeRequest(HttpServletRequest.class);
1131 if (request != null) {
1132 HttpServletResponse response = webRequest.getNativeRequest(HttpServletResponse.class);
1133 initContextHolders(request, buildLocaleContext(request), buildRequestAttributes(request, response, null));
1134 }
1135 }
1136 @Override
1137 public <T> void postProcess(NativeWebRequest webRequest, Callable<T> task, Object concurrentResult) {
1138 HttpServletRequest request = webRequest.getNativeRequest(HttpServletRequest.class);
1139 if (request != null) {
1140 resetContextHolders(request, null, null);
1141 }
1142 }
1143 }
1144
1145 }