or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

configuration.mdcontroller-annotations.mdfunctional-web.mdindex.mdresource-handling.mdservlet-framework.mdsupport-utilities.mdview-resolution.md

support-utilities.mddocs/

0

# Support Utilities

1

2

Spring MVC provides various support classes and utilities for servlet initialization, request context access, URI building, internationalization, and other cross-cutting concerns.

3

4

## Capabilities

5

6

### Servlet Initialization

7

8

#### AbstractDispatcherServletInitializer

9

10

Base class for WebApplicationInitializer implementations that register a DispatcherServlet in a Servlet 3.0+ environment.

11

12

```java { .api }

13

/**

14

* Base class for WebApplicationInitializer implementations that register a DispatcherServlet.

15

*/

16

public abstract class AbstractDispatcherServletInitializer extends AbstractContextLoaderInitializer {

17

18

/** Create the servlet application context */

19

protected abstract WebApplicationContext createServletApplicationContext();

20

21

/** Specify servlet mappings for the DispatcherServlet */

22

protected abstract String[] getServletMappings();

23

24

/** Return the name to use for the DispatcherServlet */

25

protected String getServletName();

26

27

/** Get application context initializers for the servlet context */

28

protected ApplicationContextInitializer<?>[] getServletApplicationContextInitializers();

29

30

/** Get filters to apply to the DispatcherServlet */

31

protected Filter[] getServletFilters();

32

33

/** Return whether async is supported for the DispatcherServlet */

34

protected boolean isAsyncSupported();

35

36

/** Return the order to use for the DispatcherServlet */

37

protected int getOrder();

38

39

/** Customize DispatcherServlet registration */

40

protected void customizeRegistration(ServletRegistration.Dynamic registration);

41

}

42

```

43

44

#### AbstractAnnotationConfigDispatcherServletInitializer

45

46

WebApplicationInitializer to register a DispatcherServlet and use Java-based Spring configuration.

47

48

```java { .api }

49

/**

50

* WebApplicationInitializer implementation that registers a DispatcherServlet configured with annotated classes.

51

*/

52

public abstract class AbstractAnnotationConfigDispatcherServletInitializer extends AbstractDispatcherServletInitializer {

53

54

/** Specify @Configuration and/or @Component classes for the root application context */

55

protected abstract Class<?>[] getRootConfigClasses();

56

57

/** Specify @Configuration and/or @Component classes for the servlet application context */

58

protected abstract Class<?>[] getServletConfigClasses();

59

}

60

```

61

62

**Usage Examples:**

63

64

```java

65

public class WebAppInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {

66

67

@Override

68

protected Class<?>[] getRootConfigClasses() {

69

return new Class<?>[] { RootConfig.class };

70

}

71

72

@Override

73

protected Class<?>[] getServletConfigClasses() {

74

return new Class<?>[] { WebConfig.class };

75

}

76

77

@Override

78

protected String[] getServletMappings() {

79

return new String[] { "/" };

80

}

81

82

@Override

83

protected Filter[] getServletFilters() {

84

return new Filter[] {

85

new CharacterEncodingFilter("UTF-8", true),

86

new HiddenHttpMethodFilter(),

87

new HttpPutFormContentFilter()

88

};

89

}

90

91

@Override

92

protected void customizeRegistration(ServletRegistration.Dynamic registration) {

93

registration.setMultipartConfig(new MultipartConfigElement("/tmp", 5000000, 5000000, 0));

94

registration.setAsyncSupported(true);

95

}

96

}

97

98

// Alternative with manual configuration

99

public class ManualWebAppInitializer extends AbstractDispatcherServletInitializer {

100

101

@Override

102

protected WebApplicationContext createServletApplicationContext() {

103

AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext();

104

context.register(WebConfig.class);

105

return context;

106

}

107

108

@Override

109

protected String[] getServletMappings() {

110

return new String[] { "/api/*" };

111

}

112

113

@Override

114

protected WebApplicationContext createRootApplicationContext() {

115

AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext();

116

context.register(RootConfig.class);

117

return context;

118

}

119

}

120

```

121

122

### Request Context Utilities

123

124

#### RequestContextUtils

125

126

Utility class for easy access to request-specific state established by DispatcherServlet.

127

128

```java { .api }

129

/**

130

* Utility class for easy access to request-specific state which has been set by the DispatcherServlet.

131

*/

132

public abstract class RequestContextUtils {

133

134

/** Find WebApplicationContext for this request */

135

public static WebApplicationContext findWebApplicationContext(HttpServletRequest request);

136

137

/** Find WebApplicationContext, with fallback to global context */

138

public static WebApplicationContext findWebApplicationContext(HttpServletRequest request, ServletContext servletContext);

139

140

/** Get LocaleResolver for this request */

141

public static LocaleResolver getLocaleResolver(HttpServletRequest request);

142

143

/** Get Locale for this request */

144

public static Locale getLocale(HttpServletRequest request);

145

146

/** Get TimeZone for this request */

147

public static TimeZone getTimeZone(HttpServletRequest request);

148

149

/** Get ThemeResolver for this request */

150

public static ThemeResolver getThemeResolver(HttpServletRequest request);

151

152

/** Get Theme for this request */

153

public static Theme getTheme(HttpServletRequest request);

154

155

/** Get input FlashMap for this request */

156

public static FlashMap getInputFlashMap(HttpServletRequest request);

157

158

/** Get output FlashMap for this request */

159

public static FlashMap getOutputFlashMap(HttpServletRequest request);

160

161

/** Get FlashMapManager for this request */

162

public static FlashMapManager getFlashMapManager(HttpServletRequest request);

163

164

/** Get MultipartResolver for this request */

165

public static MultipartResolver getMultipartResolver(HttpServletRequest request);

166

}

167

```

168

169

**Usage Examples:**

170

171

```java

172

@Controller

173

public class UtilityController {

174

175

@GetMapping("/context-info")

176

@ResponseBody

177

public Map<String, Object> getContextInfo(HttpServletRequest request) {

178

Map<String, Object> info = new HashMap<>();

179

180

// Get application context

181

WebApplicationContext context = RequestContextUtils.findWebApplicationContext(request);

182

info.put("contextId", context.getId());

183

info.put("displayName", context.getDisplayName());

184

185

// Get locale information

186

Locale locale = RequestContextUtils.getLocale(request);

187

TimeZone timeZone = RequestContextUtils.getTimeZone(request);

188

info.put("locale", locale.toString());

189

info.put("timeZone", timeZone.getID());

190

191

// Get flash map

192

FlashMap inputFlashMap = RequestContextUtils.getInputFlashMap(request);

193

if (inputFlashMap != null && !inputFlashMap.isEmpty()) {

194

info.put("flashAttributes", inputFlashMap);

195

}

196

197

return info;

198

}

199

200

@PostMapping("/set-flash")

201

public String setFlashAttribute(HttpServletRequest request, RedirectAttributes redirectAttributes) {

202

// Using RedirectAttributes (preferred)

203

redirectAttributes.addFlashAttribute("message", "Operation successful");

204

205

// Or using RequestContextUtils directly

206

FlashMap outputFlashMap = RequestContextUtils.getOutputFlashMap(request);

207

if (outputFlashMap != null) {

208

outputFlashMap.put("timestamp", System.currentTimeMillis());

209

}

210

211

return "redirect:/context-info";

212

}

213

}

214

```

215

216

### URI Building Utilities

217

218

#### ServletUriComponentsBuilder

219

220

UriComponentsBuilder with additional static factory methods to create URLs based on the current HttpServletRequest.

221

222

```java { .api }

223

/**

224

* UriComponentsBuilder with additional static factory methods based on the current HttpServletRequest.

225

*/

226

public class ServletUriComponentsBuilder extends UriComponentsBuilder {

227

228

/** Create builder from context path of current request */

229

public static ServletUriComponentsBuilder fromContextPath(HttpServletRequest request);

230

231

/** Create builder from servlet mapping of current request */

232

public static ServletUriComponentsBuilder fromServletMapping(HttpServletRequest request);

233

234

/** Create builder from request URI of current request */

235

public static ServletUriComponentsBuilder fromRequestUri(HttpServletRequest request);

236

237

/** Create builder from current request */

238

public static ServletUriComponentsBuilder fromRequest(HttpServletRequest request);

239

240

/** Create builder from current context path (requires request context) */

241

public static ServletUriComponentsBuilder fromCurrentContextPath();

242

243

/** Create builder from current servlet mapping (requires request context) */

244

public static ServletUriComponentsBuilder fromCurrentServletMapping();

245

246

/** Create builder from current request URI (requires request context) */

247

public static ServletUriComponentsBuilder fromCurrentRequestUri();

248

249

/** Create builder from current request (requires request context) */

250

public static ServletUriComponentsBuilder fromCurrentRequest();

251

252

/** Remove the specified query parameters */

253

public ServletUriComponentsBuilder removeQueryParams(String... queryParams);

254

255

/** Replace the query string entirely */

256

public ServletUriComponentsBuilder replaceQuery(String query);

257

}

258

```

259

260

**Usage Examples:**

261

262

```java

263

@RestController

264

@RequestMapping("/api/users")

265

public class UserApiController {

266

267

@PostMapping

268

public ResponseEntity<User> createUser(@RequestBody User user, HttpServletRequest request) {

269

User savedUser = userService.save(user);

270

271

// Build location header using current request

272

URI location = ServletUriComponentsBuilder

273

.fromCurrentRequest()

274

.path("/{id}")

275

.buildAndExpand(savedUser.getId())

276

.toUri();

277

278

return ResponseEntity.created(location).body(savedUser);

279

}

280

281

@GetMapping

282

public ResponseEntity<PagedResponse<User>> getUsers(

283

@RequestParam(defaultValue = "0") int page,

284

@RequestParam(defaultValue = "10") int size,

285

HttpServletRequest request) {

286

287

Page<User> users = userService.findAll(PageRequest.of(page, size));

288

289

// Build pagination links

290

String baseUrl = ServletUriComponentsBuilder

291

.fromCurrentRequest()

292

.replaceQueryParams(null) // Remove all query params

293

.toUriString();

294

295

Map<String, String> links = new HashMap<>();

296

links.put("self", baseUrl + "?page=" + page + "&size=" + size);

297

298

if (users.hasNext()) {

299

links.put("next", baseUrl + "?page=" + (page + 1) + "&size=" + size);

300

}

301

if (users.hasPrevious()) {

302

links.put("prev", baseUrl + "?page=" + (page - 1) + "&size=" + size);

303

}

304

305

PagedResponse<User> response = new PagedResponse<>(users.getContent(), links);

306

return ResponseEntity.ok(response);

307

}

308

309

@GetMapping("/search")

310

public String buildSearchUrl(HttpServletRequest request) {

311

return ServletUriComponentsBuilder

312

.fromRequest(request)

313

.replaceQuery("q={keyword}&type={type}")

314

.build()

315

.toUriString();

316

}

317

}

318

319

@Controller

320

public class WebController {

321

322

@GetMapping("/form")

323

public String showForm(Model model) {

324

// Build form action URL

325

String actionUrl = ServletUriComponentsBuilder

326

.fromCurrentServletMapping()

327

.path("/submit")

328

.toUriString();

329

330

model.addAttribute("actionUrl", actionUrl);

331

return "form";

332

}

333

334

@PostMapping("/submit")

335

public String submitForm(@ModelAttribute FormData formData) {

336

// Process form

337

return "redirect:" + ServletUriComponentsBuilder

338

.fromCurrentContextPath()

339

.path("/success")

340

.queryParam("id", formData.getId())

341

.toUriString();

342

}

343

}

344

```

345

346

### Internationalization Support

347

348

#### LocaleResolver Implementations

349

350

See the main documentation for LocaleResolver interface. Here are additional implementation details:

351

352

```java

353

@Configuration

354

public class LocaleConfig {

355

356

@Bean

357

public LocaleResolver localeResolver() {

358

CookieLocaleResolver resolver = new CookieLocaleResolver();

359

resolver.setDefaultLocale(Locale.ENGLISH);

360

resolver.setCookieName("locale");

361

resolver.setCookieMaxAge(3600);

362

resolver.setCookiePath("/");

363

return resolver;

364

}

365

366

@Bean

367

public LocaleChangeInterceptor localeChangeInterceptor() {

368

LocaleChangeInterceptor interceptor = new LocaleChangeInterceptor();

369

interceptor.setParamName("lang");

370

return interceptor;

371

}

372

373

@Override

374

public void addInterceptors(InterceptorRegistry registry) {

375

registry.addInterceptor(localeChangeInterceptor());

376

}

377

}

378

379

@Controller

380

public class LocaleController {

381

382

@GetMapping("/locale-info")

383

@ResponseBody

384

public Map<String, Object> getLocaleInfo(HttpServletRequest request, HttpServletResponse response) {

385

LocaleResolver localeResolver = RequestContextUtils.getLocaleResolver(request);

386

Locale currentLocale = localeResolver.resolveLocale(request);

387

388

Map<String, Object> info = new HashMap<>();

389

info.put("currentLocale", currentLocale.toString());

390

info.put("language", currentLocale.getLanguage());

391

info.put("country", currentLocale.getCountry());

392

info.put("displayName", currentLocale.getDisplayName());

393

394

return info;

395

}

396

397

@PostMapping("/change-locale")

398

public String changeLocale(@RequestParam String locale,

399

HttpServletRequest request,

400

HttpServletResponse response) {

401

LocaleResolver localeResolver = RequestContextUtils.getLocaleResolver(request);

402

localeResolver.setLocale(request, response, Locale.forLanguageTag(locale));

403

404

String referer = request.getHeader("Referer");

405

return "redirect:" + (referer != null ? referer : "/");

406

}

407

}

408

```

409

410

### Flash Map Support

411

412

#### FlashMap and FlashMapManager

413

414

See main documentation for interfaces. Here are usage patterns:

415

416

```java

417

@Controller

418

public class FlashMapController {

419

420

@PostMapping("/process")

421

public String processData(@ModelAttribute ProcessData data,

422

HttpServletRequest request,

423

RedirectAttributes redirectAttributes) {

424

425

try {

426

processService.process(data);

427

428

// Using RedirectAttributes (preferred)

429

redirectAttributes.addFlashAttribute("successMessage", "Data processed successfully");

430

redirectAttributes.addFlashAttribute("processedData", data);

431

432

} catch (ProcessingException e) {

433

// Using FlashMap directly for complex scenarios

434

FlashMap flashMap = RequestContextUtils.getOutputFlashMap(request);

435

flashMap.put("errorMessage", e.getMessage());

436

flashMap.put("errorCode", e.getErrorCode());

437

flashMap.put("inputData", data);

438

439

// Set target for flash attributes

440

flashMap.setTargetRequestPath("/error");

441

Map<String, String> targetParams = new HashMap<>();

442

targetParams.put("type", "processing");

443

flashMap.setTargetRequestParams(new LinkedMultiValueMap<>(targetParams));

444

445

return "redirect:/error?type=processing";

446

}

447

448

return "redirect:/success";

449

}

450

451

@GetMapping("/success")

452

public String showSuccess(Model model, HttpServletRequest request) {

453

// Flash attributes are automatically added to model

454

// But can also be accessed directly

455

FlashMap inputFlashMap = RequestContextUtils.getInputFlashMap(request);

456

if (inputFlashMap != null) {

457

log.info("Flash attributes received: {}", inputFlashMap.keySet());

458

}

459

460

return "success";

461

}

462

463

@GetMapping("/error")

464

public String showError(@RequestParam String type, Model model, HttpServletRequest request) {

465

FlashMap inputFlashMap = RequestContextUtils.getInputFlashMap(request);

466

if (inputFlashMap != null && inputFlashMap.containsKey("errorMessage")) {

467

model.addAttribute("errorDetails", inputFlashMap);

468

}

469

470

return "error";

471

}

472

}

473

```

474

475

### JSP Tag Library Support

476

477

#### RequestContextAwareTag

478

479

Abstract base class for JSP tags that need access to the RequestContext.

480

481

```java { .api }

482

/**

483

* Superclass for all tags that require a RequestContext.

484

*/

485

public abstract class RequestContextAwareTag extends TagSupport {

486

487

/** Get the current RequestContext */

488

protected final RequestContext getRequestContext();

489

490

/** Template method for tag start processing */

491

protected abstract int doStartTagInternal() throws Exception;

492

}

493

```

494

495

#### MessageTag

496

497

JSP tag for message resolution using MessageSource.

498

499

```java { .api }

500

/**

501

* Custom tag for retrieving message from MessageSource.

502

*/

503

public class MessageTag extends RequestContextAwareTag {

504

505

/** Set the message code */

506

public void setCode(String code);

507

508

/** Set message arguments */

509

public void setArguments(Object arguments);

510

511

/** Set MessageSourceResolvable object */

512

public void setMessage(MessageSourceResolvable message);

513

514

/** Set scope for storing the result */

515

public void setScope(String scope);

516

517

/** Set variable name for storing the result */

518

public void setVar(String var);

519

520

/** Set text to output if message not found */

521

public void setText(String text);

522

523

/** Set HTML escaping flag */

524

public void setHtmlEscape(boolean htmlEscape);

525

}

526

```

527

528

#### UrlTag

529

530

JSP tag for creating URLs with proper encoding and context path handling.

531

532

```java { .api }

533

/**

534

* JSP tag for creating URLs. Modeled after the JSTL c:url tag.

535

*/

536

public class UrlTag extends RequestContextAwareTag {

537

538

/** Set the URL value */

539

public void setValue(String value);

540

541

/** Set the context path */

542

public void setContext(String context);

543

544

/** Set variable name for storing the result */

545

public void setVar(String var);

546

547

/** Set scope for storing the result */

548

public void setScope(String scope);

549

550

/** Set HTML escaping flag */

551

public void setHtmlEscape(boolean htmlEscape);

552

553

/** Set JavaScript escaping flag */

554

public void setJavaScriptEscape(boolean javaScriptEscape);

555

}

556

```

557

558

**JSP Tag Usage Examples:**

559

560

```jsp

561

<%@ taglib prefix="spring" uri="http://www.springframework.org/tags" %>

562

563

<!-- Message resolution -->

564

<spring:message code="welcome.message" />

565

<spring:message code="user.greeting" arguments="${user.name}" />

566

<spring:message code="error.required" var="requiredMsg" />

567

568

<!-- URL creation -->

569

<spring:url value="/users/${user.id}" var="userUrl" />

570

<a href="${userUrl}">View User</a>

571

572

<spring:url value="/static/css/styles.css" context="/myapp" var="cssUrl" />

573

<link rel="stylesheet" href="${cssUrl}" />

574

```

575

576

### Complete Internationalization Support

577

578

#### LocaleResolver Interface

579

580

```java { .api }

581

/**

582

* Interface for web-based locale resolution strategies.

583

*/

584

public interface LocaleResolver {

585

586

/** Resolve the locale for the given request */

587

Locale resolveLocale(HttpServletRequest request);

588

589

/** Set the current locale */

590

void setLocale(HttpServletRequest request, HttpServletResponse response, Locale locale);

591

}

592

```

593

594

#### AcceptHeaderLocaleResolver

595

596

```java { .api }

597

/**

598

* LocaleResolver implementation that uses the primary locale specified in the Accept-Language header.

599

*/

600

public class AcceptHeaderLocaleResolver implements LocaleResolver {

601

602

/** Set supported locales */

603

public void setSupportedLocales(List<Locale> locales);

604

605

/** Get supported locales */

606

public List<Locale> getSupportedLocales();

607

608

/** Set default locale */

609

public void setDefaultLocale(Locale defaultLocale);

610

611

/** Get default locale */

612

public Locale getDefaultLocale();

613

}

614

```

615

616

#### SessionLocaleResolver

617

618

```java { .api }

619

/**

620

* LocaleResolver implementation that uses a locale attribute in the user's session.

621

*/

622

public class SessionLocaleResolver implements LocaleResolver {

623

624

/** Set the name of the session attribute holding the locale */

625

public void setLocaleAttributeName(String localeAttributeName);

626

627

/** Get the session attribute name */

628

public String getLocaleAttributeName();

629

630

/** Set default locale */

631

public void setDefaultLocale(Locale defaultLocale);

632

633

/** Set default time zone */

634

public void setDefaultTimeZone(TimeZone defaultTimeZone);

635

}

636

```

637

638

**Complete Internationalization Configuration:**

639

640

```java

641

@Configuration

642

public class CompleteI18nConfig {

643

644

@Bean

645

public MessageSource messageSource() {

646

ResourceBundleMessageSource messageSource = new ResourceBundleMessageSource();

647

messageSource.setBasenames("messages", "validation");

648

messageSource.setDefaultEncoding("UTF-8");

649

messageSource.setCacheSeconds(3600);

650

messageSource.setFallbackToSystemLocale(false);

651

return messageSource;

652

}

653

654

@Bean

655

public LocaleResolver localeResolver() {

656

SessionLocaleResolver resolver = new SessionLocaleResolver();

657

resolver.setDefaultLocale(Locale.ENGLISH);

658

resolver.setDefaultTimeZone(TimeZone.getTimeZone("UTC"));

659

return resolver;

660

}

661

662

@Bean

663

public LocaleChangeInterceptor localeChangeInterceptor() {

664

LocaleChangeInterceptor interceptor = new LocaleChangeInterceptor();

665

interceptor.setParamName("lang");

666

interceptor.setHttpMethods("GET", "POST");

667

interceptor.setIgnoreInvalidLocale(true);

668

return interceptor;

669

}

670

671

// Alternative with Accept-Language header

672

@Bean

673

public LocaleResolver acceptHeaderLocaleResolver() {

674

AcceptHeaderLocaleResolver resolver = new AcceptHeaderLocaleResolver();

675

resolver.setSupportedLocales(Arrays.asList(

676

Locale.ENGLISH,

677

Locale.FRENCH,

678

Locale.GERMAN,

679

new Locale("es")

680

));

681

resolver.setDefaultLocale(Locale.ENGLISH);

682

return resolver;

683

}

684

}

685

```

686

687

### Exception Handling Utilities

688

689

```java

690

@ControllerAdvice

691

public class GlobalExceptionHandler {

692

693

@ExceptionHandler(NoHandlerFoundException.class)

694

public ModelAndView handleNotFound(NoHandlerFoundException ex, HttpServletRequest request) {

695

ModelAndView mv = new ModelAndView("error/404");

696

mv.addObject("url", ex.getRequestURL());

697

mv.addObject("method", ex.getHttpMethod());

698

mv.addObject("message", "The requested resource was not found");

699

mv.setStatus(HttpStatus.NOT_FOUND);

700

return mv;

701

}

702

703

@ExceptionHandler(Exception.class)

704

public ModelAndView handleGeneral(Exception ex, HttpServletRequest request) {

705

ModelAndView mv = new ModelAndView("error/500");

706

mv.addObject("exception", ex);

707

mv.addObject("url", request.getRequestURL().toString());

708

mv.addObject("timestamp", new Date());

709

mv.setStatus(HttpStatus.INTERNAL_SERVER_ERROR);

710

711

// Add request context information

712

WebApplicationContext context = RequestContextUtils.findWebApplicationContext(request);

713

if (context != null) {

714

mv.addObject("contextInfo", context.getDisplayName());

715

}

716

717

return mv;

718

}

719

}

720

```