Struts2 Validation behaving weird - java

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.

Related

Unable to get query string params in struts 2 action class

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

Adding #RequiredStringValidator causing result not to be found

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.

Declatring Struts 2 actions as annotation

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>

using struts 2 action for a simple ajax request

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

Exception thrown by an interceptor doesn't go to the exception handler.

There's an issue I've experienced this day. I have an interceptor that begins and commits a Hibernate transaction and it may throw an exception on commit (org.hibernate.StaleObjectStateException for instance). That is, it can throw an exception but exception doesn't get to the handler. I thought there's an issue in my code. But then I wrote a simple test and here it is
Package definition in struts.xml:
<package name="basicstruts2" namespace="/" extends="struts-default">
<interceptors>
<interceptor name="dummy" class="test.TestInterceptor"/>
<interceptor-stack name="myStack">
<interceptor-ref name="defaultStack" />
<interceptor-ref name="dummy" />
</interceptor-stack>
</interceptors>
<default-interceptor-ref name="myStack"/>
<global-results>
<result name="exception" type="chain">exceptionHandler</result>
</global-results>
<global-exception-mappings>
<exception-mapping exception="java.lang.Exception" result="exception" />
</global-exception-mappings>
<action name="test" class="test.TestAction">
<result>result.jsp</result>
</action>
<action name="exceptionHandler" class="test.ExceptionHandler">
<result>DebugErrorPage.jsp</result>
</action>
</package>
TestAction.java:
package test;
public class TestAction extends ActionSupport {
private BusinessLogic logic = new BusinessLogic();
public String execute() {
logic.test();
return SUCCESS;
}
}
TestInterceptor.java:
package test;
public class TestInterceptor implements Interceptor {
#Override
public String intercept(ActionInvocation arg0) throws Exception {
String result = null;
try {
result = arg0.invoke();
boolean flag = true;
if (flag) throw new RuntimeException("qwerty");
} catch (Exception e) {
System.out.println("exception catched in interceptor, rethrowing " + e);
throw e;
}
return result;
}
}
ExceptionHandler.java:
package test;
public class ExceptionHandler extends ActionSupport {
private Exception exception;
public void setException(Exception e) {
exception = e;
System.out.println("setting exception");
}
public String execute() {
System.out.println("exeption in handler " + exception);
return SUCCESS;
}
}
BusinessLogic.java:
package test;
public class BusinessLogic {
public void test() {
System.out.println("test logic");
// boolean flag = true;
// if (flag) throw new RuntimeException("qwerty");
}
}
So, console output :
test logic
exception catched in interceptor, rethrowing java.lang.RuntimeException: qwerty
BUT if an exception is thrown by BusinnesLogic, we can uncomment code:
BusinessLogic.java:
package test;
public class BusinessLogic {
public void test() {
System.out.println("test logic");
boolean flag = true;
if (flag) throw new RuntimeException("qwerty");
}
}
and comment out code in interceptor:
#Override
public String intercept(ActionInvocation arg0) throws Exception {
String result = null;
try {
result = arg0.invoke();
// boolean flag = true;
// if (flag) throw new RuntimeException("qwerty");
} catch (Exception e) {
System.out.println("exception catched in interceptor, rethrowing " + e);
throw e;
}
return result;
}
output will be:
test logic
exception catched in interceptor, rethrowing java.lang.RuntimeException: qwerty
setting exception
exeption in handler java.lang.RuntimeException: qwerty
And we will see the error page.
So, can anybody give a good explanation of this behavior? What's the point of putting the exception interceptor at the top of the default struts stack if it can't handle exceptions that was thrown by other interceptors? and why??
I would really appreciate for a good answer.
EDIT:
There is a code I have a problem with:
public String intercept(ActionInvocation arg0) throws Exception {
String result = null;
try {
sf.getCurrentSession().beginTransaction();
result = arg0.invoke();
sf.getCurrentSession().getTransaction().commit();
} catch (StaleObjectStateException staleEx) {
if (sf.getCurrentSession().getTransaction().isActive()) {
sf.getCurrentSession().getTransaction().rollback();
}
throw staleEx;
} catch (Exception ex) {
ex.printStackTrace();
try {
if (sf.getCurrentSession().getTransaction().isActive()) {
sf.getCurrentSession().getTransaction().rollback();
}
} catch (Throwable rbEx) {
}
// Let others handle it... maybe another interceptor for exceptions?
throw new ServletException(ex);
}
return result;
}
What should be done if I want handle exceptions thrown on commit() ?
The exception is thrown by TestInterceptor after the action invocation and result rendering.
From the note on the Writing Interceptors page:
Keep in mind that invoke will return after the result has been called (eg. after you JSP has been rendered), making it perfect for things like open-session-in-view patterns. If you want to do something before the result gets called, you should implement a PreResultListener.
Core Functionality of ExceptionMappingInterceptor
This interceptor forms the core functionality of the exception handling feature. Exception handling allows you to map an exception to a result code, just as if the action returned a result code instead of throwing an unexpected exception. When an exception is encountered, it is wrapped with an ExceptionHolder and pushed on the stack, providing easy access to the exception from within your result. Note: While you can configure exception mapping in your configuration file at any point, the configuration will not have any effect if this interceptor is not in the interceptor stack for your actions. It is recommended that you make this interceptor the first interceptor on the stack, ensuring that it has full access to catch any exception, even those caused by other interceptors.
Example code:
<xwork>
<package name="default" extends="xwork-default">
<global-results>
<result name="error" type="freemarker">error.ftl</result>
</global-results>
<global-exception-mappings>
<exception-mapping exception="java.lang.Exception" result="error"/>
</global-exception-mappings>
<action name="test">
<interceptor-ref name="exception"/>
<interceptor-ref name="basicStack"/>
<exception-mapping exception="com.acme.CustomException" result="custom_error"/>
<result name="custom_error">custom_error.ftl</result>
<result name="success" type="freemarker">test.ftl</result>
</action>
</package>
</xwork>

Categories