You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@struts.apache.org by lu...@apache.org on 2022/04/04 15:36:43 UTC

[struts-site] 01/01: Adds a guideline how to create an extension point

This is an automated email from the ASF dual-hosted git repository.

lukaszlenart pushed a commit to branch extension-points
in repository https://gitbox.apache.org/repos/asf/struts-site.git

commit 88cacbf5c153d85ec4a2da51ba2543d455165b61
Author: Lukasz Lenart <lu...@apache.org>
AuthorDate: Mon Apr 4 17:36:34 2022 +0200

    Adds a guideline how to create an extension point
---
 source/plugins/index.md                |   4 +-
 source/plugins/plugins-architecture.md | 305 +++++++++++++++++++++++++++++++++
 source/plugins/plugins.md              | 207 ----------------------
 3 files changed, 307 insertions(+), 209 deletions(-)

diff --git a/source/plugins/index.md b/source/plugins/index.md
index bf0b8fc08..c102e6eb0 100644
--- a/source/plugins/index.md
+++ b/source/plugins/index.md
@@ -5,11 +5,11 @@ title: Plugins
 
 # Plugin Developers Guide
 
-Apache Struts 2 provides a simple [plugin architecture](plugins) so that developers can extend the framework just by
+Apache Struts 2 provides a simple [plugin architecture](plugins-architecture) so that developers can extend the framework just by
 adding a JAR to the application's classpath. Since plugins are contained in a JAR, they are easy to share with others.
 Several plugins are bundled with the framework, and others are available from third-party sources.
 
-- [Plugins](plugins)
+- [Plugins](plugins-architecture)
 - [Extending an Application with Custom Plugins](extending-an-application-with-custom-plugins)
 
 ## Bundled Plugins
diff --git a/source/plugins/plugins-architecture.md b/source/plugins/plugins-architecture.md
new file mode 100644
index 000000000..cabc74def
--- /dev/null
+++ b/source/plugins/plugins-architecture.md
@@ -0,0 +1,305 @@
+---
+layout: default
+title: Plugins
+parent:
+  url: index.html
+  title: Plugins
+---
+
+# Plugins
+{:.no_toc}
+
+* Will be replaced with the ToC, excluding a header
+{:toc}
+
+Struts 2 plugins contain classes and configuration that extend, replace, or add to existing Struts framework functionality. 
+A plugin can be installed by adding its JAR file to the application's class path, in addition to the JAR files to fulfill
+whatever dependencies the plugin itself may have. To configure the plugin, the JAR should contain a `struts-plugin.xml` 
+file, which follows the same format as an ordinary `struts.xml` file.
+
+Since a plugin can contain the `struts-plugin.xml` file, it has the ability to:
+ - Define new packages with results, interceptors, and/or actions
+ - Override framework constants 
+ - Introduce new extension point implementation classes
+
+Many popular but optional features of the framework are distributed as plugins. An application can retain all the plugins 
+provided with the distribution, or just include the ones it uses. Plugins can be used to organize application code 
+or to distribute code to third-parties.
+
+Packages defined in a plugin can have parent packages that are defined in another plugin. Plugins may define 
+configuration elements with classes not contained in the plugin. Any classes not included in the plugin's JAR must be 
+on the application's classpath at runtime. As from Struts 2.3.5
+
+The framework loads its default configuration first, then any plugin configuration files found in others JARs
+on the classpath, and finally the "bootstrap" `struts.xml`.
+
+1. `struts-default.xml` (bundled in the Core JAR)
+2. `struts-plugin.xml` (as many as can be found in other JARs)
+3. `struts.xml` (provided by your application)
+
+Since the `struts.xml` file is always loaded last, it can make use of any resources provided by the plugins bundled
+with the distribution, or any other plugins available to an application.
+
+## Static resources
+
+To include static resources in your plugins add them under "/static" in your jar. And include them in your page using 
+"/static" as the path, like in the following example:
+
+```ftl
+<!-- Assuming /static/main.css is inside a plugin jar, to add it to the page: -->
+
+<@s.url value="/struts/main.css" var="css" />
+<link rel="stylesheet" type="text/css" href="%{#css}" />
+```
+
+Read also [Static Content](../core-developers/static-content) and JavaDoc of [StaticContentLoader](https://struts.apache.org/maven/struts2-core/apidocs/org/apache/struts2/dispatcher/StaticContentLoader).
+
+## Extension Points
+
+Extension points allow a plugin to override a key class in the Struts framework with an alternate implementation. 
+For example, a plugin could provide a new class to create Action classes or map requests to Actions.
+
+The following extension points are available in Struts 2:
+
+| Property                                | Description                                                                                                                                                                                  | Scope       | Type                                                             |
+|-----------------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|-------------|------------------------------------------------------------------|
+| struts.objectFactory                    | Creates actions, results, and interceptors                                                                                                                                                   | singleton   | com.opensymphony.xwork2.ObjectFactory                            |
+| struts.objectFactory.actionFactory      | Dedicated factory used to create Actions, you can implement/extend existing one instead of defining new ObjectFactory                                                                        | singleton   | com.opensymphony.xwork2.factory.ActionFactory                    |
+| struts.objectFactory.resultFactory      | Dedicated factory used to create Results, you can implement/extend existing one instead of defining new ObjectFactory                                                                        | singleton   | com.opensymphony.xwork2.factory.ResultFactory                    |
+| struts.objectFactory.interceptorFactory | Dedicated factory used to create Interceptors, you can implement/extend existing one instead of defining new ObjectFactory                                                                   | singleton   | com.opensymphony.xwork2.factory.InterceptorFactory               |
+| struts.objectFactory.converterFactory   | Dedicated factory used to create TypeConverters, you can implement/extend existing one instead of defining new ObjectFactory                                                                 | singleton   | com.opensymphony.xwork2.factory.ConverterFactory                 |
+| struts.objectFactory.validatorFactory   | Dedicated factory used to create Validators, you can implement/extend existing one instead of defining new ObjectFactory                                                                     | singleton   | com.opensymphony.xwork2.factory.ValidatorFactory                 |
+| struts.actionProxyFactory               | Creates the ActionProxy                                                                                                                                                                      | singleton   | com.opensymphony.xwork2.ActionProxyFactory                       |
+| struts.objectTypeDeterminer             | Determines what the key and element class of a Map or Collection should be                                                                                                                   | singleton   | com.opensymphony.xwork2.util.ObjectTypeDeterminer                |
+| struts.mapper.class                     | Determines the ActionMapping from a request and a URI from an ActionMapping                                                                                                                  | singleton   | org.apache.struts2.dispatcher.mapper.ActionMapper                |
+| struts.multipart.parser                 | Parses a multipart request (file upload)                                                                                                                                                     | per request | org.apache.struts2.dispatcher.multipart.MultiPartRequest         |
+| struts.freemarker.manager.classname     | Loads and processes Freemarker templates                                                                                                                                                     | singleton   | org.apache.struts2.views.freemarker.FreemarkerManager            |
+| struts.velocity.manager.classname       | Loads and processes Velocity templates                                                                                                                                                       | singleton   | org.apache.struts2.views.velocity.VelocityManager                |
+| struts.actionValidatorManager           | Main interface for validation managers (regular and annotation based).  Handles both the loading of configuration and the actual validation (since 2.1)                                      | singleton   | com.opensymphony.xwork2.validator.ActionValidatorManager         |
+| struts.valueStackFactory                | Creates value stacks (since 2.1)                                                                                                                                                             | singleton   | com.opensymphony.xwork2.util.ValueStackFactory                   |
+| struts.reflectionProvider               | Provides reflection services, key place to plug in a custom expression language (since 2.1)                                                                                                  | singleton   | com.opensymphony.xwork2.reflection.ReflectionProvider            |
+| struts.reflectionContextFactory         | Creates reflection context maps used for reflection and expression language operations (since 2.1)                                                                                           | singleton   | com.opensymphony.xwork2.reflection.ReflectionContextFactory      |
+| N/A                                     | All beans registered as PackageProvider implementations will be automatically included in configuration building (since 2.1)                                                                 | singleton   | com.opensymphony.xwork2.config.PackageProvider                   |
+| struts.patternMatcher                   | Matches patterns, such as action names, generally used in configuration (since 2.1)                                                                                                          | singleton   | com.opensymphony.xwork2.util.PatternMatcher                      |
+| struts.staticContentLoader              | Loads static resources (since 2.1)                                                                                                                                                           | singleton   | org.apache.struts2.views.dispatcher.DefaultStaticContentLoader   |
+| struts.xworkConverter                   | Handles conversion logic and allows to load custom converters per class or per action                                                                                                        | singleton   | com.opensymphony.xwork2.conversion.impl.XWorkConverter           |
+| struts.localeProviderFactory            | Allows provide custom LocaleProvider for whole application                                                                                                                                   | singleton   | com.opensymphony.xwork2.LocaleProviderFactory                    |
+| struts.urlRenderer                      | Allows provide custom implementation of environment specific URL rendering/creating class                                                                                                    | singleton   | org.apache.struts2.components.UrlRenderer                        |
+| struts.unknownHandlerManager            | Implementation of this interface allows handle logic of unknown Actions, Methods or Results                                                                                                  | singleton   | com.opensymphony.xwork2.UnknownHandlerManager                    |
+| struts.view.urlHelper                   | Helper class used with URLRenderer to provide exact logic for building URLs                                                                                                                  | singleton   | org.apache.struts2.views.util.UrlHelper                          |
+| struts.fileManagerFactory               | Used to create FileManager instance to access files on the File System as also to monitor if reload is needed, can be implemented / overwritten to meet specific an application server needs | singleton   | com.opensymphony.xwork2.FileManagerFactory                       |
+| struts.converter.collection             | Converter used to convert any object to Collection and back                                                                                                                                  | singleton   | com.opensymphony.xwork2.conversion.impl.CollectionConverter      |
+| struts.converter.array                  | Converter used to convert any object to Array and back                                                                                                                                       | singleton   | com.opensymphony.xwork2.conversion.impl.ArrayConverter           |
+| struts.converter.date                   | Converter used to convert any object to Date and back                                                                                                                                        | singleton   | com.opensymphony.xwork2.conversion.impl.DateConverter            |
+| struts.converter.number                 | Converter used to convert any object to Number and back                                                                                                                                      | singleton   | com.opensymphony.xwork2.conversion.impl.NumberConverter          |
+| struts.converter.string                 | Converter used to convert any object to String and back                                                                                                                                      | singleton   | com.opensymphony.xwork2.conversion.impl.StringConverter          |
+| struts.conversion.properties.processor  | Process Properties to create converters                                                                                                                                                      | singleton   | com.opensymphony.xwork2.conversion.ConversionPropertiesProcessor |
+| struts.converter.file.processor         | Process {class}-conversion.properties file create converters                                                                                                                                 | singleton   | com.opensymphony.xwork2.conversion.ConversionPropertiesProcessor |
+| struts.converter.annotation.processor   | Process TypeConversion annotation to create converters                                                                                                                                       | singleton   | com.opensymphony.xwork2.conversion.ConversionAnnotationProcessor |
+| struts.converter.creator                | Creates user converters                                                                                                                                                                      | singleton   | com.opensymphony.xwork2.conversion.TypeConverterCreator          |
+| struts.converter.holder                 | Holds user converters' instances                                                                                                                                                             | singleton   | com.opensymphony.xwork2.conversion.TypeConverterHolder           |
+| struts.expression.parser                | Used to parse expressions like ${foo.bar} or %{bar.foo} but it is up tp the TextParser's implementation what kind of opening char to use (#, $, %, etc)                                      | singleton   | com.opensymphony.xwork2.util.TextParser                          |
+| struts.excludedPatterns.checker         | Used across different interceptors to check if given string matches one of the excluded patterns                                                                                             | request     | com.opensymphony.xwork2.ExcludedPatternsChecker                  |
+| struts.acceptedPatterns.checker         | Used across different interceptors to check if given string matches one of the accepted patterns                                                                                             | request     | com.opensymphony.xwork2.AcceptedPatternsChecker                  |
+| struts.contentTypeMatcher               | Matches content type of uploaded files (since 2.3.22)                                                                                                                                        | singleton   | org.apache.struts2.util.ContentTypeMatcher                       |
+| struts.localizedTextProvider            | Provides access to resource bundles used to localise messages (since 2.5.11)                                                                                                                 | singleton   | com.opensymphony.xwork2.LocalizedTextProvider                    |
+| struts.date.formatter                   | Allow define a date formatter used by `<s:date/>` tag (since 6.0.0)                                                                                                                          | singleton   | org.apache.struts2.components.date.DateFromatter                 |
+
+## Plugin Examples
+
+Let's look at two similar but different plugins bundled with the core distribution.
+
+### Sitemesh plugin
+
+[SiteMesh](http://opensymphony.com/sitemesh/) is a popular alternative to Tiles. SiteMesh provides a common look-and-feel
+to an application's pages by automatically wrapping a plain page with common elements like headers and menubars.
+
+The `sitemesh-plugin.jar` contains several classes, a standard JAR manifest, and a plugin configuration file.
+
+````text
+ + META-INF/
+   + manifest.mf
+ + org
+   + apache
+     + struts2
+       + sitemesh
+         + FreeMarkerPageFilter.class
+         + TemplatePageFilter.class
+         + VelocityPageFilter.class
+ + struts-plugin.xml
+````
+
+While the SiteMesh Plugin doesn't provide any new results, interceptors, or actions, or even extend any Struts integration 
+points, it does need to know what settings have been enabled in the Struts framework. Therefore, its `struts-plugin.xml` looks like this:
+
+{% comment %}start snippet lang=xml|https://gitbox.apache.org/repos/asf?p=struts.git;a=blob_plain;f=plugins/sitemesh/src/main/resources/struts-plugin.xml;hb=HEAD  {% endcomment %}
+
+```xml
+<?xml version="1.0" encoding="UTF-8" ?>
+<!--
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+-->
+<!DOCTYPE struts PUBLIC
+	"-//Apache Software Foundation//DTD Struts Configuration 2.5//EN"
+	"http://struts.apache.org/dtds/struts-2.5.dtd">
+    
+<struts>
+    <bean class="org.apache.struts2.sitemesh.FreemarkerPageFilter" static="true" optional="true"/>
+    <bean class="org.apache.struts2.sitemesh.VelocityPageFilter" static="true" optional="true"/>
+</struts>
+
+```
+
+{% comment %}end snippet lang=xml|https://gitbox.apache.org/repos/asf?p=struts.git;a=blob_plain;f=plugins/sitemesh/src/main/resources/struts-plugin.xml;hb=HEAD  {% endcomment %}
+
+The two bean elements, with the "static" flag enabled, tell Struts to inject the current settings and framework objects 
+into static property setters on startup. This allows, for example, the FreeMarkerPageFilter class to get an instance 
+of the Struts FreemarkerManager and the current encoding setting.
+
+### Tiles plugin
+
+[Tiles](http://struts.apache.org/struts-sandbox/tiles/index) is a popular alternative to SiteMesh. Tiles provides 
+a common look-and-feel to an application's pages by breaking the page down into common fragments or "tiles".
+
+The `tiles-plugin.jar` contains several classes, a standard JAR manifest, and a configuration file.
+
+```text
+ + META-INF/
+   + manifest.mf
+ + org
+   + apache
+     + struts2
+       + tiles
+         + StrutsTilesListener.class
+         + StrutsTileUtilImpl.class
+       + views
+         + tiles
+           + TilesResult.class
+   + struts-plugin.xml
+```
+
+Since the Tiles Plugin does need to register configuration elements, a result class, it provides a `struts-plugin.xml` file.
+
+## Developing new extension point
+
+An extension point it's a name which will be used to locate other beans by the name and inject them into a given place.
+Extension point isn't a bean, you cannot inject it. It's a bridge between your interface/class and the final implementation,
+provided either by a plugin or by a user.
+
+If needed you can define your own extension point. This can happen in two ways: either define it in the Struts Core,
+or define the extension in the plugin you are developing.
+
+### Extension point provided by the Core
+
+First step is to name your extension point, basically we are using a pattern like follow:
+```
+struts.<component | functionallity>.<name of the extebsion point>
+```
+
+e.g.: `struts.date.formatter`.
+
+Now you must provide an interface or a class as the extension point, it will be used by others to implement they own behaviour
+of the extension point, e.g.: `org.apache.struts2.components.date.DateFormatter`.
+
+The next step is to tie the name of the extension point with the interface/class. It happens in `StrutsBeanSelectionProvider`
+
+by using `alias()` method as below:
+```java
+alias(DateFormatter.class, StrutsConstants.STRUTS_DATE_FORMATTER, builder, props, Scope.SINGLETON);
+```
+
+as you can see you must provide:
+ - `Class<?>` class behind the extension point, which is used by users to implement the extension point
+ - `String` a key, the name of the extension point
+ - `ContainerBuilder` builder used to setup the Container
+ - `Properties` additional properties when needed
+ - `Scope` scope of the extension point, all the beans extneding the extension point must have the same scope
+
+Having all that set, you can define where to use the extension point by injecting beans implementing it by using `@Inject`
+
+```java
+@Inject
+public void setDateFormatter(DateFormatter dateFormatter) {
+    this.dateFormatter = dateFormatter;
+}
+```
+
+you can use `optional = true` if the implementation is not required, yet please remember to handle `null` in such case.
+
+All the above steps have defined a new extension point, now you can implement a bean which will be _bridged_ throughout
+the extension point with the `@Inject`. Just implement the interface/class used to define the extension point and define
+the bean in `struts-default.xml`:
+
+```java
+public class DateTimeFormatterAdapter implements DateFormatter {
+
+    @Override
+    public String format(TemporalAccessor temporal, String format) {
+        DateTimeFormatter dtf;
+        Locale locale = ActionContext.getContext().getLocale();
+        if (format == null) {
+            dtf = DateTimeFormatter.ofLocalizedDateTime(FormatStyle.MEDIUM)
+                .withLocale(locale);
+        } else {
+            dtf = DateTimeFormatter.ofPattern(format, locale);
+        }
+        return dtf.format(temporal);
+    }
+
+}
+```
+
+```xml
+<bean type="org.apache.struts2.components.date.DateFormatter" 
+      name="dateTimeFormatter" 
+      class="org.apache.struts2.components.date.DateTimeFormatterAdapter" 
+      scope="singleton"/>
+```
+
+The `name` attribute it's of your choice, it just needs to be unique.
+
+And the final step is to use the new bean with the extension point, this will happen in `default.properties`:
+
+```
+struts.date.formatter=dateTimeFormatter
+```
+
+and done!
+
+If a user would like to provide its own implementation they just needs to implement the interface, define a bean 
+in `struts.xml` with a name and then tie it to the extension point overriding the one provided by the framework:
+
+```xml
+<bean type="org.apache.struts2.components.date.DateFormatter" 
+      name="myDateTimeFormatter" 
+      class="com.company.date.MyDateTimeFormatterAdapter" 
+      scope="singleton"/>
+```
+
+```
+struts.date.formatter=myDateTimeFormatter
+```
+
+### Extension point provided by a plugin
+
+## Plugin Registry
+
+> For a list of bundled plugins, see the [Plugin Reference Documentation](index). For more about bundled and third-party 
+> plugins, visit the [Apache Struts Plugin Registry](http://cwiki.apache.org/S2PLUGINS/home).
diff --git a/source/plugins/plugins.md b/source/plugins/plugins.md
deleted file mode 100644
index 50b7b5401..000000000
--- a/source/plugins/plugins.md
+++ /dev/null
@@ -1,207 +0,0 @@
----
-layout: default
-title: Plugins
-parent:
-  url: index.html
-  title: Plugins
----
-
-# Plugins
-{:.no_toc}
-
-* Will be replaced with the ToC, excluding a header
-{:toc}
-
-Struts 2 plugins contain classes and configuration that extend, replace, or add to existing Struts framework functionality. 
-A plugin can be installed by adding its JAR file to the application's class path, in addition to the JAR files to fulfill
-whatever dependencies the plugin itself may have. To configure the plugin, the JAR should contain a `struts-plugin.xml` 
-file, which follows the same format as an ordinary `struts.xml` file.
-
-Since a plugin can contain the `struts-plugin.xml` file, it has the ability to:
-
-+ Define new packages with results, interceptors, and/or actions
-
-+ Override framework constants
-
-+ Introduce new extension point implementation classes
-
-Many popular but optional features of the framework are distributed as plugins. An application can retain all the plugins 
-provided with the distribution, or just include the ones it uses. Plugins can be used to organize application code 
-or to distribute code to third-parties.
-
-Packages defined in a plugin can have parent packages that are defined in another plugin. Plugins may define 
-configuration elements with classes not contained in the plugin. Any classes not included in the plugin's JAR must be 
-on the application's classpath at runtime. As from Struts 2.3.5
-
-The framework loads its default configuration first, then any plugin configuration files found in others JARs
-on the classpath, and finally the "bootstrap" `struts.xml`.
-
-1. `struts-default.xml` (bundled in the Core JAR)
-2. `struts-plugin.xml` (as many as can be found in other JARs)
-3. `struts.xml` (provided by your application)
-
-Since the `struts.xml` file is always loaded last, it can make use of any resources provided by the plugins bundled
-with the distribution, or any other plugins available to an application.
-
-## Static resources
-
-To include static resources in your plugins add them under "/static" in your jar. And include them in your page using 
-"/struts" as the path, like in the following example:
-
-```ftl
-<!-- Assuming /static/main.css is inside a plugin jar, to add it to the page: -->
-
-<@s.url value="/struts/main.css" var="css" />
-<link rel="stylesheet" type="text/css" href="%{#css}" />
-```
-
-Read also [StaticContentLoader JavaDoc](https://struts.apache.org/maven/struts2-core/apidocs/org/apache/struts2/dispatcher/StaticContentLoader).
-
-## Extension Points
-
-Extension points allow a plugin to override a key class in the Struts framework with an alternate implementation. 
-For example, a plugin could provide a new class to create Action classes or map requests to Actions.
-
-The following extension points are available in Struts 2:
-
-|Property|Description|Scope|Type|
-|--------|-----------|-----|----|
-|struts.objectFactory|Creates actions, results, and interceptors|singleton|com.opensymphony.xwork2.ObjectFactory|
-|struts.objectFactory.actionFactory|Dedicated factory used to create Actions, you can implement/extend existing one instead of defining new ObjectFactory|singleton|com.opensymphony.xwork2.factory.ActionFactory|
-|struts.objectFactory.resultFactory|Dedicated factory used to create Results, you can implement/extend existing one instead of defining new ObjectFactory|singleton|com.opensymphony.xwork2.factory.ResultFactory|
-|struts.objectFactory.interceptorFactory|Dedicated factory used to create Interceptors, you can implement/extend existing one instead of defining new ObjectFactory|singleton|com.opensymphony.xwork2.factory.InterceptorFactory|
-|struts.objectFactory.converterFactory|Dedicated factory used to create TypeConverters, you can implement/extend existing one instead of defining new ObjectFactory|singleton|com.opensymphony.xwork2.factory.ConverterFactory|
-|struts.objectFactory.validatorFactory|Dedicated factory used to create Validators, you can implement/extend existing one instead of defining new ObjectFactory|singleton|com.opensymphony.xwork2.factory.ValidatorFactory|
-|struts.actionProxyFactory|Creates the ActionProxy|singleton|com.opensymphony.xwork2.ActionProxyFactory|
-|struts.objectTypeDeterminer|Determines what the key and element class of a Map or Collection should be|singleton|com.opensymphony.xwork2.util.ObjectTypeDeterminer|
-|struts.mapper.class|Determines the ActionMapping from a request and a URI from an ActionMapping|singleton|org.apache.struts2.dispatcher.mapper.ActionMapper|
-|struts.multipart.parser|Parses a multipart request (file upload)|per request|org.apache.struts2.dispatcher.multipart.MultiPartRequest|
-|struts.freemarker.manager.classname|Loads and processes Freemarker templates|singleton|org.apache.struts2.views.freemarker.FreemarkerManager|
-|struts.velocity.manager.classname|Loads and processes Velocity templates|singleton|org.apache.struts2.views.velocity.VelocityManager|
-|struts.actionValidatorManager|Main interface for validation managers (regular and annotation based).  Handles both the loading of configuration and the actual validation (since 2.1)|singleton|com.opensymphony.xwork2.validator.ActionValidatorManager|
-|struts.valueStackFactory|Creates value stacks (since 2.1)|singleton|com.opensymphony.xwork2.util.ValueStackFactory|
-|struts.reflectionProvider|Provides reflection services, key place to plug in a custom expression language (since 2.1)|singleton|com.opensymphony.xwork2.reflection.ReflectionProvider|
-|struts.reflectionContextFactory|Creates reflection context maps used for reflection and expression language operations (since 2.1)|singleton|com.opensymphony.xwork2.reflection.ReflectionContextFactory|
-|N/A|All beans registered as PackageProvider implementations will be automatically included in configuration building (since 2.1)|singleton|com.opensymphony.xwork2.config.PackageProvider|
-|struts.patternMatcher|Matches patterns, such as action names, generally used in configuration (since 2.1)|singleton|com.opensymphony.xwork2.util.PatternMatcher|
-|struts.staticContentLoader|Loads static resources (since 2.1)|singleton|org.apache.struts2.views.dispatcher.DefaultStaticContentLoader|
-|struts.xworkConverter|Handles conversion logic and allows to load custom converters per class or per action|singleton|com.opensymphony.xwork2.conversion.impl.XWorkConverter|
-|struts.localeProviderFactory|Allows provide custom LocaleProvider for whole application|singleton|com.opensymphony.xwork2.LocaleProviderFactory|
-|struts.urlRenderer|Allows provide custom implementation of environment specific URL rendering/creating class|singleton|org.apache.struts2.components.UrlRenderer|
-|struts.unknownHandlerManager|Implementation of this interface allows handle logic of unknown Actions, Methods or Results|singleton|com.opensymphony.xwork2.UnknownHandlerManager|
-|struts.view.urlHelper|Helper class used with URLRenderer to provide exact logic for building URLs|singleton|org.apache.struts2.views.util.UrlHelper|
-|struts.fileManagerFactory|Used to create FileManager instance to access files on the File System as also to monitor if reload is needed, can be implemented / overwritten to meet specific an application server needs|singleton|com.opensymphony.xwork2.FileManagerFactory|
-|struts.converter.collection|Converter used to convert any object to Collection and back|singleton|com.opensymphony.xwork2.conversion.impl.CollectionConverter|
-|struts.converter.array|Converter used to convert any object to Array and back|singleton|com.opensymphony.xwork2.conversion.impl.ArrayConverter|
-|struts.converter.date|Converter used to convert any object to Date and back|singleton|com.opensymphony.xwork2.conversion.impl.DateConverter|
-|struts.converter.number|Converter used to convert any object to Number and back|singleton|com.opensymphony.xwork2.conversion.impl.NumberConverter|
-|struts.converter.string|Converter used to convert any object to String and back|singleton|com.opensymphony.xwork2.conversion.impl.StringConverter|
-|struts.conversion.properties.processor|Process Properties to create converters|singleton|com.opensymphony.xwork2.conversion.ConversionPropertiesProcessor|
-|struts.converter.file.processor|Process {class}-conversion.properties file create converters|singleton|com.opensymphony.xwork2.conversion.ConversionPropertiesProcessor|
-|struts.converter.annotation.processor|Process TypeConversion annotation to create converters|singleton|com.opensymphony.xwork2.conversion.ConversionAnnotationProcessor|
-|struts.converter.creator|Creates user converters|singleton|com.opensymphony.xwork2.conversion.TypeConverterCreator|
-|struts.converter.holder|Holds user converters' instances|singleton|com.opensymphony.xwork2.conversion.TypeConverterHolder|
-|struts.expression.parser|Used to parse expressions like ${foo.bar} or %{bar.foo} but it is up tp the TextParser's implementation what kind of opening char to use (#, $, %, etc)|singleton|com.opensymphony.xwork2.util.TextParser|
-|struts.excludedPatterns.checker|Used across different interceptors to check if given string matches one of the excluded patterns|request|com.opensymphony.xwork2.ExcludedPatternsChecker|
-|struts.acceptedPatterns.checker|Used across different interceptors to check if given string matches one of the accepted patterns|request|com.opensymphony.xwork2.AcceptedPatternsChecker|
-|struts.contentTypeMatcher|Matches content type of uploaded files (since 2.3.22)|singleton|org.apache.struts2.util.ContentTypeMatcher|
-|struts.localizedTextProvider|Provides access to resource bundles used to localise messages (since 2.5.11)|singleton|com.opensymphony.xwork2.LocalizedTextProvider|
-
-## Plugin Examples
-
-Let's look at two similar but different plugins bundled with the core distribution.
-
-### Sitemesh plugin
-
-[SiteMesh](http://opensymphony.com/sitemesh/) is a popular alternative to Tiles. SiteMesh provides a common look-and-feel
-to an application's pages by automatically wrapping a plain page with common elements like headers and menubars.
-
-The `sitemesh-plugin.jar` contains several classes, a standard JAR manifest, and a plugin configuration file.
-
-````text
- + META-INF/
-   + manifest.mf
- + org
-   + apache
-     + struts2
-       + sitemesh
-         + FreeMarkerPageFilter.class
-         + TemplatePageFilter.class
-         + VelocityPageFilter.class
- + struts-plugin.xml
-````
-
-While the SiteMesh Plugin doesn't provide any new results, interceptors, or actions, or even extend any Struts integration 
-points, it does need to know what settings have been enabled in the Struts framework. Therefore, its `struts-plugin.xml` looks like this:
-
-{% comment %}start snippet lang=xml|https://gitbox.apache.org/repos/asf?p=struts.git;a=blob_plain;f=plugins/sitemesh/src/main/resources/struts-plugin.xml;hb=HEAD  {% endcomment %}
-
-```xml
-<?xml version="1.0" encoding="UTF-8" ?>
-<!--
-/*
- * $Id$
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
--->
-<!DOCTYPE struts PUBLIC
-	"-//Apache Software Foundation//DTD Struts Configuration 2.5//EN"
-	"http://struts.apache.org/dtds/struts-2.5.dtd">
-    
-<struts>
-    <bean class="org.apache.struts2.sitemesh.FreemarkerPageFilter" static="true" optional="true"/>
-    <bean class="org.apache.struts2.sitemesh.VelocityPageFilter" static="true" optional="true"/>
-</struts>
-
-```
-
-{% comment %}end snippet lang=xml|https://gitbox.apache.org/repos/asf?p=struts.git;a=blob_plain;f=plugins/sitemesh/src/main/resources/struts-plugin.xml;hb=HEAD  {% endcomment %}
-
-The two bean elements, with the "static" flag enabled, tell Struts to inject the current settings and framework objects 
-into static property setters on startup. This allows, for example, the FreeMarkerPageFilter class to get an instance 
-of the Struts FreemarkerManager and the current encoding setting.
-
-### Tiles plugin
-
-[Tiles](http://struts.apache.org/struts-sandbox/tiles/index) is a popular alternative to SiteMesh. Tiles provides 
-a common look-and-feel to an application's pages by breaking the page down into common fragments or "tiles".
-
-The `tiles-plugin.jar` contains several classes, a standard JAR manifest, and a configuration file.
-
-```text
- + META-INF/
-   + manifest.mf
- + org
-   + apache
-     + struts2
-       + tiles
-         + StrutsTilesListener.class
-         + StrutsTileUtilImpl.class
-       + views
-         + tiles
-           + TilesResult.class
-   + struts-plugin.xml
-```
-
-Since the Tiles Plugin does need to register configuration elements, a result class, it provides a `struts-plugin.xml` file.
-
-## Plugin Registry
-
-> For a list of bundled plugins, see the [Plugin Reference Documentation](index). For more about bundled and third-party 
-> plugins, visit the [Apache Struts Plugin Registry](http://cwiki.apache.org/S2PLUGINS/home).