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).