[ 
https://issues.apache.org/struts/browse/WW-2826?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
 ]

James Holmes updated WW-2826:
-----------------------------

    Fix Version/s: Future

> Make struts2 more component-friendly
> ------------------------------------
>
>                 Key: WW-2826
>                 URL: https://issues.apache.org/struts/browse/WW-2826
>             Project: Struts 2
>          Issue Type: New Feature
>    Affects Versions: 2.1.2
>            Reporter: Sami Dalouche
>             Fix For: Future
>
>
> Contrary to component-oriented frameworks , Struts2 architecture does not try 
> to ignore what the web is, it just tries to make web programming easier 
> without introducing complex component lifecycles.
> However, there are a few things that the component-oriented frameworks got 
> right, and I believe struts2 should build on its architecture to enable users 
> to create UI components easily. 
> These needs arise from the project I am currently working on, and I describe 
> the hacks that I currently do to 'simulate' components. I also try to 
> envision the features that struts2 could add to make writing components 
> easier. This 'request' should be seen as a meta-feature request that can be 
> used as a basis for discussing what should be included. Once everybody 
> agrees, we can create smaller issues that target individual concerns.
> So, let's define what a reusable UI component needs to work decently:
> - Markup template. (the view)
> - Custom CSS for the component
> - Custom JavaScript for the component
> - Access to helper Java code 
> - Access to a given model, expressed as a Java class that has to be pushed on 
> the value stack, so that it can catch URL/form parameters related to the 
> component
> - When the component displays part of a form, the action has to delegate part 
> of the validation to the component's model, using @VisitorFieldValidator
> - a Custom interceptor to set parameters on the action
> - Custom properties file for I18N
> Frameworks such as tapestry have built-in features for all these concerns. 
> Here is the struts2-way to achieve the same, with the current feature set :
> - Markup/View: Markup template expressed as FTL, either using the Struts2 
> Component / Taglib infrastructure, or just plain FTL files that have nothing 
> to do with struts2
> - Custom CSS and JavaScript either sourced or included in a specific 
> @component.head  tag. the developer is responsible for including head in the 
> head section of the page.  The head macro has to be coded in a way that does 
> not include JS / CSS directly, but first checks if it hasn't already be 
> included, in case several components transitively depend on a given component 
> and call it's head as part of the head tag/macro. Also, the tag is 
> responsible to use either the real .css/.js file, or the one generated by the 
> build system in case there are hooks to merge CSS and JS files in order to 
> reduce the number of requests.
> - Helper java functions have to be registered using a Custom Freemarker 
> Manager. Adding helpers to the freemarker context is pretty straightforward, 
> but adding the services to the ValueStack too is a little tricky. You have to 
> make sure you don't  push the same service twice in the same request, because 
> populateContext() is called several times...
> - The component's java model has to be pushed by the action. pretty much like 
> the action's view has to reference the head tag in the head section. I use a 
> MultipleModelDrivenInterceptor that works like ModelDrivenInterceptor, except 
> that is pushes a list of objects, instead of just one.  In case the component 
> adds fields to the form, the action is responsible for adding 
> @VisitorFieldValidator. 
> - For important parameters and session attributes that are considered 
> globally accessible on the website, specific interceptors + *Aware interfaces 
> can be used to ease the actions' job. Things like Users, etc, can be directly 
> injected to the action to avoid boilerplate copy/pasted code.
> - Each component has its own properties file, that is registered in 
> struts.xml as a global resource bundle.
> OK, now, why I think all this stuff is suboptimal :
> - There is no common concept in struts that defines what a component is. so 
> all the pieces are available, but it looks like tricks and hacks that we try 
> to get to work. It would definitely be less worrying for the developer if 
> struts provided an 'official' way to do it.
> - the developer is responsible for adding head to the HTML head section, for 
> creating the component's Java Model, for pushing it on the value stack, and 
> for delegating validation to the component. WAO !!! In most cases, if you're 
> not the one who developed the component, you will forget one of these steps.  
> - The developer is responsible for making sure keys are globally unique among 
> components... Hum... Once again, this gives the impression of a mere hack...
>  Pushing some resource bundle using the I18N tag is not an option since it 
> renders the use of <#nested> useless. For instance, if a component did :
> <@s.i18n name="myComponentResourceBundle>
>  <@s.text name="whatever.key.in.component.resource.bundle" />
>  <#nested />
> </@s.i18n>
> then if the component is called with <@s.text /> code in the <#nested /> 
> section, the <@s.text would not find its key in the component resource 
> bundle, and would then fail. Implementing a fallback mechanism that would go 
> down the value stack could partly work, but would still not fix the duplicate 
> key problem. 
> - When we want to do some processing depending on the parameters, and inject 
> some variables to the current action thanks to a custom interceptor, we don't 
> have access to type converters, we basically need to do the job by hand (or 
> probably instantiate the type converters, or do whatever hardcore low level 
> struts or OGNL stuff to achieve the same). So, the only real way to bind 
> parameters is to use a custom model class that is instantiated and pushed on 
> the value stack by the action, but then the action has too much stuff to do 
> regarding the component. See previous section regarding custom java component 
> models.
> So, what I think struts could add in order to make writing components more 
> consistent and easier :
> 1] A small wiki section that describes the 'preferred' struts approach to 
> creating reusable components, whatever approach is chosen. Even if the wiki 
> section is considered as a mere suggestion, it would allow users to realize 
> that it is in fact possible to write components using struts2, and would 
> certainly help struts2 beginners. 
> 2] A kind of generic behavior that would allow components (Struts 2 Tag 
> Components) to register custom CSS and JS code, that would be printed in the 
> default struts2 themes. (<@s.head />). In order to select which components 
> are used on a page, I guess that parsing the FTL would be too weak ? So, it 
> would be acceptable to force the action to declare the list of the components 
> that are used. Do some people have an idea regarding this ?
> 3] A way for Struts2 components to declare :
> - A method to create the associated java model object, for every request 
> where the component is used. This model object should be pushed to the value 
> stack automatically.
> - the ModelDriven-validation.xml rules that should be included when the 
> component is used. The main problem I see with that is that is to allow 
> switching validation off, because the action would probably  want to validate 
> the model for the execute() method, but not the input() one. 
> - An interface that an action could implement to receive the populated model 
> (MyModelAware.class), as well as some callback method that is used to set the 
> model on the implementing action. A generic interceptor could then use 
> whatever ThreadLocal/request-scoped object to retrieve all the callback 
> methods that have to be called on the current action, depending on the types 
> implemented by the action.
> - The name of a spring/whatever IoC service that should be registered in the 
> freemarker + OGNL context, so that FTL views can refer to it
> - The name of a .properties file to use for I18N keys lookup. To make this to 
> work, my guess is that @s.text would need to be completly reworked to be 
> component aware, since both global keys, and trying eveyr textprovider in the 
> value stack both don't fix the duplicate key problems. Maybe some experts 
> have a better idea to solve this issue ?
> That's it ! (I think) :p
> So yeah, still a lot of questions, it's definitely a tough problem, but I 
> really believe it's worth thinking a little bit about that.
> In my project, I am progressively starting to extract abstractions to create 
> components, so don't hesitate to bring your ideas to complement what I 
> suggested. I would happily share the code that implements these ideas 
> whenever it is available.
> Regards,
> Sami Dalouche

-- 
This message is automatically generated by JIRA.
-
You can reply to this email to add a comment to the issue online.

Reply via email to