Struts 2 dynamic value attribute in s:property - struts2

I have an Action class and a Data class like below
Action Class
public class TestAction extends ActionSupport{
private Data aData;
}
Data class
public class Data {
private char v1;
private char v2; etc till 17;
public accessors for all variables above;
}
My jsp is like below
JSP snippet
<s:set var="varName" value="'data.v'"/>
<s:iterator var="idx" begin="1" end="17">
<s:set var="prop" value="#varName+#idx"/>
<s:property value="<WHAT TO DO HERE TO GET THE VALUES STORED IN THE VARIABLES>"
</s:iterator
Whatever I put in the s:property tag's value attribute, (%{#prop}, #arr#prop, [prop]), I get the literal Strings data.v1, data.v2, ... data.v17 in my output and NOT the values stored in the data.v1, data.v2, etc. variables.
Can you please let me know how I can get the values stored in the data object.
Edit based on duplicate question suggestion struts-2-warning-the-default-value-expression-contains-evaluated-to-nullnu
The suggested question is a double evaluation of the value in the variable, whereas what I am looking for is a double evaluation of the variable. After submitting my original question, I came across another question with a comment that the double evaluation I am looking for is not supported. I have mentioned this as a comment in my own question, requesting for confirmation as it was not quite clear in the other question as well.

Related

How to print a list of objects in a Velocity template?

This is a pretty basic problem and I'm pretty sure I'm doing something wrong or making some assumption. Here goes.
I'm writing a Jira plugin, which uses the Velocity template system. I have a list of ResultRow objects where ResultRow is a class with a single member variable: String key:
public class ResultRow {
public String key;
}
I have a list of these ResultRows:
List<ResultRow> rows = new ArrayList<ResultRow>();
ResultRow row = new ResultRow();
row.key = "foo";
rows.add(foo);
Map<String, Object> velocityParams = new HashMap<String, Object>();
velocityParams.put("rows", rows);
return descriptor.getHtml("view", velocityParams);
and I am trying to list these rows in a template with the following:
#foreach ($row in $rows)
<tr><td>$row.key</td></tr>
#end
I want the output to be: foo. Maddeningly, the template system simply prints the literal string "$row.key" instead of the contents of key. To verify that "$row" is indeed an object, I used the template:
#foreach ($row in $rows)
<tr><td>$row</td></tr>
#end
and the result was as expected: com.domain.jira.ResultRow#7933f2c6.
I think maybe I'm missing some requirement for the class. Does it need to be defined in some special way to suggest to Velocity that certain members are usable in templates? Does Jira use some special funky version of Velocity that only works with certain objects?
I guess the answer is you cannot do what I was trying to do. You can call member methods but you can't access member variables, which means you'll need to add getters to your class. (Could've sworn I tried that. Ah well.)
Velocity does not expose fields, only methods. There are ways to change that:
You can create your own Uberspect class that allows access to public fields.
You can wrap the instance with a modified version of Velocity's FieldMethodizer that gives access to non-static fields.
You can add and use an instance of a "tool" class to your context, such as a subclass of VelocityTool's ClassTool.

beans properties and modelDriven in struts 2

I am new to struts 2. I created an action class that insert data from JSP page to a bean using ModelDriven interface.
The problem is that i have some non 'Stringproperties in the bean likeLong,Date` ... etc
The problem is:
when i press submit button in the jsp page i get an error saying that it did not find the a string setter for that particular property.
for example if i have in my bean
package com.hsms.aseza.enteringApproval
Class EnteringApproval
private Date approvalDate
Date getApprovalDate()
{
return employeeId;
}
void setApprovalDate(Date employeeId)
{
this.employeeId = employeeId;
}
when the action class that implement the model driven is executed, it fires a run time exception
java.lang.NoSuchMethodException: com.hsms.aseza.enteringApproval.EnteringApproval.setApprovalDate([Ljava.lang.String;)
Is there anyway to solve this problem without writing a String setter for my Date property?
I think that your problem is conversion i.e. conversion from String to your java.util.Date Object. This class extends this which is responsible for converting from String to other types like Long, Double etc. If you check the source code for DefaultTypeConverter, you won't see any conversion for either java.util.Date or java.sql.Date. So i think what you should do is to write a converter for approvalDate. My previous post on this will guide you on the procedure, all you will need is to edit the code to suit your needs.
On your jsp, follow this datepicker example
Use the same format i.e date format used to display your date in your jsp with SimpleDateFormat to do your conversion in convertFromString method of your converter and return the converted java.util.Date or java.sql.Date.
Let me know if you have issues implementing this.
Try use the s:date tag in your jsp.
Edit:
Try use:
<s:textfield key="objEnteringApproval.approvalDate"></s:textfield>
in which objEnteringApproval is your public accessible variable in your controller.
Make sure you have initialized your bean in your action class
Private YourBean bean = new YourBean();
Or you can have it in the constructor
Make sure your getter and setter are public
If you are trying to type date on the jsp page, please use datepicker e.g. sx:datetimepicker or sj:datepicker

asp.net mvc 3 validation on data type

I am trying to realize valition on data type. I have used DataAnnotations, but for data type it's not showing customized message
for example when I' am trying enter string data into int typed field. How I can customize messages in this case?
If I had to guess, you sound like you want a custom message to display when validating one or more fields in your model. You can subclass the DataAnnotations.ValidationAttribute class and override the IsValid(object) method and finally setting a custom ErrorMessage value (where ErrorMessage already belongs to the ValidationAttribute class)
public class SuperDuperValidator : ValidationAttribute
{
public override bool IsValid(object value)
{
bool valid = false;
// do your validation logic here
return valid;
}
}
Finally, decorate your model property with the attribute
public class MyClass
{
[SuperDuperValidator(ErrorMessage="Something is wrong with MyInt")]
public int MyInt { get; set; }
}
If you're using out-of-the-box MVC3, this should be all you need to propertly validate a model (though your model will probably differ/have more properties, etc) So, in your [HttpPost] controller action, MVC will automagically bind MyClass and you will be able to use ModelState.IsValid to determine whether or not the posted data is, in fact, valid.
Pavel,
The DataAnnotations DataType attribute does not affect validation. It's used to decide how your input is rendered. In such a case, David's solution above works.
However, if you want to use only the built-in validation attributes, you probably need to use the Range attribute like this:
[Range(0, 10, ErrorMessage="Please enter a number between 0 and 10")]
public int MyInt { get ; set ;}
(Of course, you should really be using the ErrorMessageResourceName/Type parameters and extract out hard-coded error message strings into resx files.)
Make sure to let MVC know where to render your error message:
<%= Html.ValidationMessageFor(m => m.MyInt) %>
Or you can just use EditorForModel and it will set it up correctly.
I don't think this has been answered because I have the same issue.
If you have a Model with a property of type int and the user types in a string of "asd" then the MVC3 framework binding/validation steps in and results in your view displaying "The value 'asd' is not valid for <model property name or DisplayName here>".
To me the poster is asking can this message that the MVC3 framework is outputting be customized?
I'd like to know too. Whilst the message is not too bad if you label your field something that easily indicates an number is expected you might still want to include additional reasons so it says something like:
"The value 'asd' is not valid for <fieldname>; must be a positive whole number."
So that the user is not entering value after value and getting different error messages each time.

Struts2 xwork Type Conversion - Multiple different parameters into one Object

Is it possible to convert different paremeters into one object on your action?
Say from my html form, I pass in variables, "firstname", "lastname". Can I write a type converter that will convert those into a Person object on my action?
I didn't see any examples of this, and I don't see API. I don't see how I can access the value stack in the StrutsTypeConverter to get to the other variables.
Thanks!
Example :
// JavaBeans
public class Person {
#Getter #Setter private String firstname;
#Getter #Setter private String lastname;
}
// Action
#Setter private Person person;
// form
<s:form>
<s:textfield name="person.firstname" />
<s:textfield name="person.lastname" />
</s:form>
Similar example : vaannila : Domain Object as JavaBeans Property
I am agree what lschin said.you can use the build in OGNL and value stack combination to achieve what you want.still if u need some specific type conversion machanism here are the details from the Struts2 docs
Struts2 Type Conversion

Asp.Net MVC 1.0 custom Modelbinders - how to handle form posts and parameter names?

I have a custom model binding:
using System.Web.Mvc;
using MyProject.Model;
namespace MyProject.ModelBinders
{
public class VersionedIdModelBinder : IModelBinder
{
public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
{
//Not completely happy with this. What if the parameter was named something besides id?
return VersionedId.Parse(bindingContext.ValueProvider["id"].RawValue.ToString());
}
}
}
which works as long as the id is passed in the url (either explicitly or via a route definition.) However, if the Id is passed in a form as a hidden input field:
<input type="hidden" id="id" name="id" value="12a" />
Then ValueProvider["id"].RawValue is a string array, so the code below doesn't behave as expected.
In the controller code, I expect to simply be able to do:
public ActionResult MyAction(VersionedId id)
{
...
}
Two questions:
I am surprised that passing the id via form post causes the RawValue to be a string array. Is this the expected behavior, and is the "standard" way to handle this to check the type of the RawValue? I need to be able to handle both form posts and url routes.
Is it normal to check for the Name of the parameter in the model binder, or is there another way to do this whereby the controller action can use whatever parameter name it likes?
Regarding your question 1, there is some interesting discussion posted Custom ModelBinder and Release Candidate.
The RawValue property is what is
consumed by the ConvertTo() method,
while the AttemptedValue property is
what is consumed by the validation
system to provide an error message.
To see an example of this, break into
one of your action methods and inspect
the Controller.ValueProvider entries.
Some of the RawValue entries will be
strings (like those from Routing),
some of them will be string arrays
(like those from QueryString or Form),
etc. The reason for the
differentiation between RawValue and
AttemptedValue is that RawValue
supports passing array types to the
ConvertTo() method. We can't convert
to a multi-element array from a single
AttemptedValue, but we can convert to
a multi-element array from a RawValue
that is itself an array. This
supports the infrastructure to allow
binding to collection types.
I agree about the unfortunate naming, though unfortunately this isn't likely to change. :(
You could directly access
controllerContext.HttpContext.Request["id"]
and get the value from there. Should be a simple string in that case.

Resources