struts2 trim all string obtained from forms
I develop web application using struts2. I want to improve getting string from forms. For this need trim all string and if obtained string is empty then set null to field.
For this, I created StringConverter.
public class StringConverter extends StrutsTypeConverter {
开发者_如何转开发 @Override
public Object convertFromString(Map context, String[] strings, Class toClass) {
if (strings == null || strings.length == 0) {
return null;
}
String result = strings[0];
if (result == null) {
return null;
}
result = result.trim();
if (result.isEmpty()) {
return null;
}
return result;
}
@Override
public String convertToString(Map context, Object object) {
if (object != null && object instanceof String) {
return object.toString();
}
return null;
}
}
Next, I added row to xwork-conversion.properties
java.lang.String=com.mypackage.StringConverter
Thats all. But I did not get the desired result.
convertToString() method is called when jsp build form, but convertFromString() doesn't invoke.
What I do wrong? How can I get the same behaviour using another way?
Please, not offer solutions such as:
- remove the value of such form elements using javascript.
- create util method which will make it using reflection. Then call it for each form bean.
Thanks in advance, Alexey.
You will find the answer in the code of the StrutsTypeConverter class. Basically, at this level the type converter framework does not know anything about whether the data is coming "from" or "to" the user, it merely knows it is converting from one type (String) to another type (also String). And since it checks the "to" type first, it will always call convertToString.
To cut a long story short, the current version of Struts (2.1.x is what I'm using) does not and cannot support String-to-String type converters. Since they are, after all, type converters you can probably say that this is by design.
I'm also looking for a way to achieve a similar result, but haven't found a really good solution yet. Probably the most "correct" approach would be to write an interceptor (as @leonbloy mentioned). There would be several ways to approach this, the most straightforward being to trim all the request parameters before they are set on the action (i.e. before the "params" interceptor executes).
Seems right to me. Are you sure convertFromString is not even called ?
Another approach you might try is to write an Interceptor that trims all params (one frequently wants that).
I don't do Struts2, but similar problem has manifested in JSF until version 1.2 in 2006 (JSF is Sun's MVC framework, the competitor of Struts2). Converting to String
was impossible in JSF as well "by design". Older JSF versions used to check if the target type equals java.lang.String
and then it just sets the request parameter value in the model without attempting to convert it (because the request parameter value is already obtained as String
). If the target type was been different, then it will locate and run any associated converter to convert it to the desired target type (which is other than String
). Since JSF 1.2 they fixed it by removing the check of the target type and locating the converter at any way.
I won't be surprised if similar feature/bug exist in Struts2. I would look around at their homepage if there isn't already an issue/bug report about that and otherwise post one.
Referred from this blog, I made a small modification in the code and it works fine. This is not any struts related utility but you can achieve your need.
Here is the utility class :
package com.company.project.common.helpers;
import java.io.Serializable;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
/**
*
* <b>File Name :</b> <i>BeanUtils.java</i> <br>
* <b>Description :</b>
* <p>
* This class contains the activities of skill program. <br/>
* <br/>
* <b>Copyright :</b> Copyright© yyyy description
* </p>
* <h1>Version History :</h1>
*
* Date : 20-06-2013<br/>
* Description : First Draft
*
* @version 1.0.0.1
* @since 1.0.0.0.1
* @author visruth
*
*/
public class BeanUtils implements Serializable {
/**
* This method trims all String variables defined in the bean if they have
* corresponding getter setter methods. <br/>
* Eg : BeanUtils beanUtils=new BeanUtils();<br/>
* StudentVO studentVO=new StudentVO();<br/>
* studentVO.setName(" foo ");<br/>
* studentVO.setAddress(" bar ");<br/>
* beanUtils.trimAllStrings(studentVO);<br/>
* System.out.println(studentVO.getName());//prints foo<br/>
* System.out.println(studentVO.getAddress());//prints bar<br/>
*
* @param beanObject
* @throws Exception
* If a variable has its getter method defined but not setter
* method will throw NoSuchMethodException instance as
* Exception.
* @author visruth
*/
public void trimAllStrings(Object beanObject) throws Exception {
Exception noSuchMethodException = null;
boolean throwNoSuchMethodException = false;
if (beanObject != null) {
Method[] methods = null;
try {
methods = beanObject.getClass().getMethods();
} catch (SecurityException e) {
throw new Exception(e);
}
if (methods != null) {
for (Method method : methods) {
String methodName = method.getName();
if (!methodName.equals("getClass")) {
String returnType = method.getReturnType().toString();
String commonMethodName = null;
if (methodName.startsWith("get")
&& "class java.lang.String".equals(returnType)) {
commonMethodName = methodName.replaceFirst("get",
"");
String returnedValue = null;
try {
returnedValue = (String) method
.invoke(beanObject);
} catch (IllegalArgumentException e) {
e.printStackTrace();
throw e;
} catch (IllegalAccessException e) {
e.printStackTrace();
throw e;
} catch (InvocationTargetException e) {
e.printStackTrace();
throw e;
}
if (returnedValue != null) {
StringBuilder setterMethodName = new StringBuilder();
setterMethodName.append("set");
setterMethodName.append(commonMethodName);
Method setterMethod = null;
try {
setterMethod = beanObject
.getClass()
.getMethod(
setterMethodName.toString(),
String.class);
if (setterMethod != null) {
if(returnedValue.isEmpty()) {
Object o=null;
setterMethod.invoke(beanObject, o);
} else {
setterMethod.invoke(beanObject,
(returnedValue.trim()));
}
}
} catch (SecurityException e) {
e.printStackTrace();
throw e;
} catch (NoSuchMethodException e) {
e.printStackTrace();
if (!throwNoSuchMethodException) {
noSuchMethodException = e;
}
throwNoSuchMethodException = true;
} catch (IllegalArgumentException e) {
e.printStackTrace();
throw e;
} catch (IllegalAccessException e) {
e.printStackTrace();
throw e;
} catch (InvocationTargetException e) {
e.printStackTrace();
throw e;
}
}
}
}
}
}
}
if (throwNoSuchMethodException && noSuchMethodException != null) {
throw noSuchMethodException;
}
}
}
To try :
package com.company.project.common.valueobject;
import java.io.Serializable;
import com.company.project.common.helpers.BeanUtils;
public class DetailsVO implements Serializable {
private static final long serialVersionUID = 6378955155265367593L;
private String firstName;
private String lastName;
private String address;
private double latitude;
private double longitude;
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public double getLatitude() {
return latitude;
}
public void setLatitude(double latitude) {
this.latitude = latitude;
}
public double getLongitude() {
return longitude;
}
public void setLongitude(double longitude) {
this.longitude = longitude;
}
public static void main(String[] args) {
BeanUtils beanUtils = new BeanUtils();
DetailsVO profileVO = new DetailsVO();
profileVO.setFirstName("");
profileVO.setLastName(" last name ");
profileVO.setAddress(" address ");
System.out.println(profileVO.getFirstName());
System.out.println(profileVO.getLastName());
System.out.println(profileVO.getAddress());
try {
beanUtils.trimAllStrings(profileVO);
} catch (Exception e) {
e.printStackTrace();
}
System.out.println(profileVO.getFirstName());
System.out.println(profileVO.getLastName());
System.out.println(profileVO.getAddress());
}
}
And gives this output :
last name
address
null
last name
address
精彩评论