I want to create a custom template engine like velocity or freemarker which will be used in struts 2 based application. Why I don't want to use any of the available template engines is because, I want to keep the HMTL fixed and editable by dreamweaver means no struts tags or JSTL. The values will be injected with Xpath or simple string replacement of values of existing HTML tags. I require:
plain HTML + some configuration (properties/xml) + data =>
HTML populated with data + some dynamically generated javascripts
1) Define a package with the name of your result type and the class that will be called when an action returns that result type.
<package name="default" namespace="/" extends="struts-default">
<result-types>
<result-type name="myResultType" class="com.awesome.MyResult"/>
</result-types>
.... actions and other things...
</package>
2) Implement the Struts 2 result type class:
package com.awesome;
public class MyResult extends StrutsResultSupport{
//1) read the the target file
//2) process/transform the target file
//3) write out the transformed file as the result
}
There is a good description of this in "Apache Struts 2 web application Development" by Dave Newton. I know the above class isn't implemented but I bet you can find what you need from here.
Related
I want to have an action default but not in XML because I want to use annotations using the Struts2 Conventions Plugin.
So I want to replace
<package abstract="true" namespace="/" name="mypackage" extends="struts-default">
<default-action-ref name="index"/>
</package>
with something in annotations, so I don't have to use a struts.xml file but also redirect to a specific action when an unknown action is specified in the URL.
Is there support for this in the Struts2 Convention Plugin or are there any good workarounds that are annotation based?
Currently there is no support but you can request at here.
I don't think that there is a simple tip or workaround!
This answer may come a bit late but still be useful to someone.
As mentioned in Struts documentation, an alternative to default actions is using wildcards:
<action name="*">
<result>/index.jsp</result>
</action>
Or using an annotation:
#Action(value = "*")
#Result(location = "/index.jsp")
public class HomeAction extends ActionSupport {
}
We have an Action class named 'Index' immediately under com.example.common.action and is annotated #ParentPackage('default') which is declared in package directive in struts.xml and has "/" for its namespace and extends "struts-default". It also declares #Result so that it responses with jsp files corresponding the string values returned by its execute() method.
In our struts.xml, the following struts setting is configured along with other necessary configurations that are needed for convention-plugin.
<constant name="struts.action.extension" value=","/>
When accessing /my_context/none_existing_path, the request apparently hits this Index class and the contents of the jsp declared in the Index's #Result section gets returned.
However, if we provide /my_context/, we receive the following error:
HTTP Status 404-There is no Action mapped for namespace[/] and action name [] associated with context path [/my_context].
We want to know the reason why accessing /my_context/none_existing_path, where none_existing_path has no matching action, can fallback to Index class, but error is returned when when the URL requested is just /my_context/.
Currently, our convention-plugin settings are declared as follows:
<constant name="struts.convention.package.locators.basePackage" value="com.example"/>
<constant name="struts.convention.package.locators" value="action"/>
Strangely, if we changed the value of the struts.convention.package.locators.basePackage to
om.example.common, in which the aforementioned Index file can be immediately found by narrowing the search scope, requesting /my_context/ displays the content of the jsps declared in #Result section of the Index class. However, as our action classes are distributed throughout the com.example.[a-z].action packages, where [a-z] represents the large volume of directories we have in our package structure, we cannot use this trick as a workaround. We have also tried placing index.jsp at the top level of the class path, and have the index.jsp redirect to /my_context/index, which worked but not what we want. Could this be a bug?
We appreciate your responses.
Thank you in advance.
EDIT: JIRA registered, problem solved (from Struts 2.3.12 up)
Try setting struts.convention.redirect.to.slash to false and see if that helps:
<constant name="struts.convention.redirect.to.slash" value="false" />
Is there a way to dynamically add an attribute to a struts 2, tag UI tag such as a textfield?
The reason is that I want to add a readOnly form field attribute to an <s:textfield/>, depending on an action's method result. I cannot use readOnly="%{isReadOnly()}" since once the attribute is defined, the form element is read-only, no matter what value it has. And wrapping each form field into an <s:if/> tag is pretty cumbersome and results in a lot of code duplication.
I would also like to avoid JavaScript for interoperability reasons and for not relying on the browser's scripting settings.
If the issue is to use the built in struts2 functionality then one easy option is to render your view with freemarker, which readily supports the dynamic addition of attributes.
If you are using conventions, it is VERY trivial you just need to create a file with a ".ftl" extension, if you are using xml it is also very easy just use the freemarker result type (see here for greater description):
<action name="test" class="package.Test">
<result name="success" type="freemarker">/WEB-INF/content/testView.ftl</result>
</action>
Here is example view using a map to dynamically add attributes (example also taken from liked page):
<#s.textfield name="test" dynamicAttributes={"placeholder":"input","foo":"bar"}/>
The dynamicAttributes would be extremely useful in all JSP UI tags but alas it is not currently implemented.
NOTE: There is one error/omission in the above link. It tells you to add the following line which causes an error in my environment (simply the line is not needed).
<#assign s=JspTaglibs["/WEB-INF/struts.tld"] />
That is, this line in a file all by it self is sufficient for rendering a text element, no explicit tag library declaration needed!
<#s.textfield name="test" dynamicAttributes={"placeholder":"input","foo":"bar"}/>
There are a number of advantages to using freemarker over plain JSPs, so taking a moment to explore the syntax and using it for this one case may prove useful later.
I have used Struts2 in a period time, but I am still very confused with Struts2 Validation.
I have used xml-validation, or method addFieldError() to validate, but when I first come to input form-page, a page with struts-tags, and a <s:form>, I can not just go to this page by a href-link, I must go through another action, I read that page jsp with struts-tags must come from a action.
And I usually create a Action just for redirect to this input page, in execute() method just "success" and the role of this action is to go to input page legally, and in action which process the input form input-page, I choose the "input" result is still this input page.
So, I feel uncomfortable to do this, I always have a GoToSiteAction, just first-time go to input page.
So, I really need your help!!.
Use the with input fields , create a action and create a validation xml file with same name as java file name
For example : AddInput.java
xml file: AddInput-validation.xml
put it in same package.
write all the validations you need for the form in xml file like this.
<field name="U_Id">
<field-validator type="requiredstring" short-circuit="true">
<message>Affiliate Id cannot be empty</message>
</field-validator>
</field>
<field name="Password">
<field-validator type="requiredstring" short-circuit="true">
<message>Password cannot be empty</message>
</field-validator>
<field-validator type="stringlength">
<param name="minLength">5</param>
<param name="maxLength">30</param>
<message>Password cannot be less than 5 or more than 30</message>
</field-validator>
</field>
When you hit the action it will first hit the validation xml and check for the validation then process the action class part.
You are not using or not using the struts2-conventions plugin to it's full effect. Please see: http://struts.apache.org/2.1.6/docs/convention-plugin.html search this page for the string "Examples of Action and Result to Template mapping" and consider the table which follows.
In the future after adding the struts2-conventions-plugin jar to your project add the postfix "-input" to the end of all future forms.
Say we created a form to add a new employee:
/WEB-INF/content/add-employee-input.jsp
The struts2 form tag would reference an action simply called "add-employee" in a java class probably named something like com.mypackages.struts2.AddEmployee then if the add-employee action validation fails then "input" is returned and the "add-employee-input" form is again rendered. However we do not need to create a "add-employee-input" action, the conventions plugin will do this for us automatically... as such we can directly enter the form if we wish by referencing it and this is very convenient.
Try it out and you'll see what I mean.
I'm new to Struts 2 and facing this problem in keeping the layout of my page:
<s:form action="abc.action"><br>
<s:textfield key="name" label="Name" /><%--here I need to display errormessage for `name`--%>
<br>
<s:textfield key="email" label="Email" /><%--here I need to display errormessage for `email`--%>
<br>
<s:submit>
</s:form>
I'm using xml-validator for my action class, this works fine. but the validation-error messages appear over the fieldname and text-box. but i want it to come afterwards respective text-box (inside another html-container). Kindly advise.
If you're used to writing HTML, switch to the simple theme.
In struts.xml is probably the best place:
<struts>
<constant name="struts.ui.theme" value="simple" />
</struts>
Then just use the fielderror tag to put the error for the field where you want it.
It's a good to be familiar with the Struts2 tags: http://struts.apache.org/release/2.3.x/docs/tag-reference.html
That is the default according to Struts2 default templating. To change it, see http://www.mkyong.com/struts2/working-with-struts-2-theme-template/
You Can also Use Struts2 validation Framework
Validation framework comes with set of useful routines to handle form validation automatically and it can handle both server side as well as client side form validation. If certain validation is not present, you can create your own validation logic by implementing java interface.
com.opensymphony.xwork2.Validator
Validator uses XML configuration files to determine which validation routines should be installed and how they should be applied for a given application. validators.xml file contains all common validators declaration. If validators.xml file is not present in classpath, a default validation file is loaded from path
com/opensymphony/xwork2/validator/validators/default.xml
Validators Scope
There are two types of Validators in Struts2 Validation Framework.
Field Validators
Non-field validators
Field validators, as the name indicate, act on single fields accessible through an action. A validator, in contrast, is more generic and can do validations in the full action context, involving more than one field (or even no field at all) in validation rule. Most validations can be defined on per field basis. This should be preferred over non-field validation wherever possible, as field validator messages are bound to the related field and will be presented next to the corresponding input element in the respecting view.
<validators>
<field name="bar">
<field-validator type="required">
<message>You must enter a value for bar.</message>
</field-validator>
</field>
</validators>
Non-field validators only add action level messages. Non-field validators are mostly domain specific and therefore offer custom implementations. The most important standard non-field validator provided by XWork is ExpressionValidator.
<validators>
<validator type="expression">
<param name="expression">foo lt bar</param>
<message>Foo must be greater than Bar.</message>
</validator>
</validators>
For whole detail example visit this link link to struts2 validation