I have an Apache Struts web application. All of my actions are defined in my struts.xml file. I am trying to add support to my action classes to have validation annotations added to my project.
To try and get this working I added the struts2-convention-plugin.jar and also commons-lang.jar.
I then added an annotation on top of my action method.
jsp
<s:form id="tradingOutageFrm" action="addTradingOutageDo.action"
validate="true" theme="simple">
struts.xml
<action name="addTradingOutageDo" class="com.myproject.action.TradingOutageAction"
method="addDo">
<result name="success" type="tiles">page.tradingOutageAdd</result>
</action>
My action class
public class TradingOutageAction extends ActionSupport {
#RequiredStringValidator(type = ValidatorType.SIMPLE,
fieldName = "storeNo",
message = "Please enter a store.")
public String addDo() throws Exception {
try{
Map<String, Object> session = ActionContext.getContext().getSession();
String userId = session.get("userid").toString();
tradingOutage.setStoreNo(storeNo);
tradingOutage.setStoreServer(storeServer);
tradingOutageDAO.insertOutage(userId, startDate, startTime,
endDate, endTime, tradingOutage);
addActionMessage(MessageConstants.RECORD_INSERTED);
}catch(Exception e){
addActionError(MessageConstants.UPDATE_FAILED + " " + e.getMessage());
}
return SUCCESS;
}
Without the annotation everything works fine but with the annotation I get a
No result defined for action com.myproject.action.TradingOutageAction and result input.
Can anyone help me with what might be wrong here.
Related
Here is my action class:
public class ForgotPassword extends ActionSupport{
private String j_username;
public String execute() throws Exception {
System.out.println("FORGOT PASSWORD ACTION CALLED");
return SUCCESS;
}
public String getUsername() {
return j_username;
}
public void setUsername(String j_username) {
System.out.println("Username received is " + j_username);
this.j_username = j_username;
}
}
I have declared default interceptors in struts.xml which includes:
<interceptor-ref name="params">
<param name="excludeParams">dojo\..*</param>
</interceptor-ref>
From html page I am sending params to action class like this:
<body>
<input type="text" id="j_username" name="j_username"/>
<div style="margin-top:20px">
<a class="forgot_password"
onclick="forgotPassword()" id="resetAnchor">Forgot Password</a>
</div>
<script type="text/javascript">
function forgotPassword() {
var ctx = '${pageContext.request.contextPath}';
var username = document.getElementById('j_username').value;
if (username !== null && username !== "") {
var username = document.getElementById('j_username').value;
console.log('username is ', username);
document.getElementById('resetAnchor').href = ctx + "/forgotPassword?j_username=" + username;
} else {
alert('please provider username');
}
}
</script>
</body>
Everything looks fine but I am unable to print this line inside setter method:
System.out.println("Username received is " + j_username);
It prints only this line: System.out.println("FORGOT PASSWORD ACTION CALLED");
Here is the action defined in struts.xml:
<action name="forgotPassword" class="com.actions.ForgotPassword">
<interceptor-ref name="params"/>
<result name="success">/reset.jsp</result>
</action>
what I'm I missing?
public String getJ_username() {
return j_username;
}
public void setJ_username(String j_username) {
System.out.println("Username received is " + j_username);
this.j_username = j_username;
}
Just change your setter and getter method. because it reads the method. not the variable name.
I think the issue is with the setter/getter methods.
Could you try this.
public String getJ_username() {
return j_username;
}
public void setJ_username( String j_username ) {
this.j_username = j_username;
}
To avoid such mistakes I suggest to use IDE help rather creating setter/getter methods on your own.
If you are using Eclipse you can follow below steps.
RightCLick on the variable you want to generate setter/getter methods.
Source ==> Generate Getters and Setters...
Check Seter and Getter check boxes click OK.
Step1
Step2
I found a code for a class in the internet which using Spring and Struts2.
I only know how to declare actions in the XML file, so in that class I found this :
#ParentPackage(value = "showcase")
public class Languages extends ActionSupport {
//deleted code
#Action(value = "/languages", results = {
#Result(type = "json", name = "success", params = {
"root", "languages"
})})
public String execute() throws Exception {
if (term != null && term.length() > 1) {
ArrayList<String> tmp = new ArrayList<String>();
for (String staticLanguage : staticLanguages) {
if (StringUtils.contains(staticLanguage.toLowerCase(), term.toLowerCase())) {
tmp.add(staticLanguage);
}
}
languages = tmp.toArray(new String[tmp.size()]);
}
return SUCCESS;
}
//deleted code
So what is the equivalent for this using the XML file for Struts2?
It's not equivalent, but is mapped to the same URL.
<package name="mypackage" namespace="/" extends="showcase">
<action name="languages" class=com.struts.Languages">
<result type="json">
<param name="root">languages</param>
</result>
</action>
</package>
I was ok to define it in struts.xml config.
<action name="getImage" class="my.action.GetImageAction">
<result name="success" type="stream">
<param name="contentType">image/jpeg</param>
<param name="inputName">imageStream</param>
<param name="bufferSize">1024</param>
</result>
</action>
And I am now trying to define it by annotation on the class with namesapce, result path, and I have no idea how to do it. Please help :)
I have tried
#Namespace("/my/namespace")
#ResultPath("/")
#Result(name = "success", type = "imageResult")
public class GetImageAction extends ActionSupport {
.....
#Override
#Action("/getImage")
public String execute() throws Exception {
.....
And I got an error
HTTP Status 404 - No result defined for action
As the error says the results have to be defined at the Action.
The definition would look like this
#Action(value = "getImage", results = { #Result(
name = "success",
type = "stream",
params = {"contentType", "application/pdf" }) })
In the example you see the type too and how to define the contentType.
And the stream will be returned by the "getFileInputStream"-method:
public InputStream getFileInputStream() {
return fileInputStream;
}
the "getContentDisposition"-Method has to be available in the Action-class
public String getContentDisposition() {
return "attachment; filename=" + getFilename() + ".pdf";
}
Here is my validate method -
#Override
public void validate() {
errors = new HashMap<String, String>();
if(StringUtil.isBlank(examCode)){
errors.put("examCode", "Exam code is required");
}
if(StringUtil.isBlank(strPaperType)){
errors.put("paperType", "Paper Type is required");
}else{
paperType = PaperType.getPaperTypeByValue(strPaperType);
if(paperType == null){
errors.put("paperType", "A valid Paper Type is required");
}
if(paperType.equals(PaperType.PRACTICE)){
if(topicId ==null){
errors.put("topicId", "Topic Id is required");
}
}
}
if(StringUtil.isBlank(instructions)){
errors.put("instructions", "Paper Instructions are required");
}
}
'errors' is my own map defined in the action. I'm not adding any errors to 'fieldErrors'. What's happening is even before entering my 'validate' method if I debug 'fieldErrors' I see following two entries -
{"id":["Invalid field value for field \"id\"."],"topicId":["Invalid field value for field \"topicId\"."]}
I have no idea from where are they getting added. Here is my struts conf.
<package name="api" extends="json-default" namespace="/api">
<action name="paper" class="paperApiAction">
<result name="json" type="json">
<param name="root">responseDto</param>
</result>
<result name="input" type="json">
<param name="root">fieldErrors</param>
</result>
</action>
</package>
Need help with this. Thanks
The "conversionError" interceptor will take type conversion errors and put them into fieldErrors. There are usecases where it's easier to take it out of the stack; I'm not sure if this is one of them or not.
Why bother duplicating the fieldErrors map? Even if you just want to have a map for use in your own DTO, why not use the existing validation mechanisms? The difference is minuscule, and a bit more flexible. You could then build the paper type validation into externalized business logic and simplify testing both it, and the action.
Unrelated, but I find your code difficult to read because of the lack of whitespace. A naive refactoring:
#Override
public void validate() {
errors = new HashMap<String, String>();
if (StringUtil.isBlank(examCode)) {
errors.put("examCode", "Exam code is required");
}
if (StringUtil.isBlank(instructions)) {
errors.put("instructions", "Paper Instructions are required");
}
if (StringUtil.isBlank(strPaperType)) {
errors.put("paperType", "Paper Type is required");
} else {
validatePaperType();
}
}
public void validatePaperType() {
paperType = PaperType.getPaperTypeByValue(strPaperType);
if (paperType == null) {
errors.put("paperType", "A valid Paper Type is required");
return;
}
if (paperType.equals(PaperType.PRACTICE) && (topicId == null)) {
errors.put("topicId", "Topic Id is required");
}
}
It seems like you id and topicId class variables are integer, but you are trying to set them as strings.
I am trying to make a simple request using AJAX . But the whole thing is not working. Below is the code I wrote
jsp/javascript :
$("#my_"+rowNum).load("getdata.action?id="+123,function(data) {
alert("i am inside "+data);
});
Struts Action :
public class MyAction extends BaseAction {
public String execute() {
try {
inputStream = new ByteArrayInputStream("ABC 123 556".getBytes("UTF-8"));
}
catch (UnsupportedEncodingException e) {
//handle exception
}
return SUCCESS;
}
}
struts.xml :
<action name="getdata" class="com.amtd.advisoradmin.action.MyAction">
<result type="stream">
<param name="contentType">text/html</param>
<param name="inputName">inputStream</param>
</result>
I feel the configuration is correct, but I don't get the alert I printed in my jsp after the control returns from the Action class. Am I missing something ?
PS : ABC 123 556 is the data I need to get in the alerts.
I would suggest you to have a private variable for inputStream type InputStream and public getter and setter for it in your Action class, which is missing.
Thanks