k_rollo
k_rollo

Reputation: 5472

Return to current page on INPUT result in Struts 2

I have an <s:form> that is present on all pages of my web application.

<s:form action="search" method="post">
    <s:textfield name="query" placeholder="Enter movie title..." cssClass="searchbox" />
    <s:submit type="image" src="images/btn_search.gif" />
</s:form>

Currently, it is redirecting to index.jsp when the validate() method of SearchAction class results to input.

<action name="search" class="com.mypackage.action.SearchAction">
    <result>/search-result.jsp</result>
    <result name="input">/index.jsp</result>
</action>

SearchAction:

public class SearchAction extends ActionSupport implements RequestAware, Message {
    private static final long serialVersionUID = 1L;

    private Map<String, Object> request;
    
    private String query;

    @Override
    public String execute() throws Exception {
        // business logic
        request.put("searchResults", searchResults);
        
        return SUCCESS;
    }
    
    @Override
    public void validate() {
        if(getQuery().length() == 0) {
            addFieldError("query", BLANK_SEARCH);
        }
    }

    @Override
    public void setRequest(Map<String, Object> request) {
        this.request = request;         
    }

    public String getQuery() {
        return query;
    }
    
    public void setQuery(String query) {
        this.query = query;
    }
}

Output:

enter image description here

It works, but it seems unnatural for the user to return to index.jsp, every time the parameter is invalid (i.e. blank).

My goal is to keep the user on the current page when the Please enter... message appears.

Questions:

  1. How do I get the current page, where the action was called?
    (For example, a visitor used the search while at the Log In page, how do I get login.jsp from the address bar?)
  2. How do I make this current page the location at
    <result name="input">/currentpage</result>?

Upvotes: 2

Views: 5870

Answers (3)

k_rollo
k_rollo

Reputation: 5472

This is just to show how I went about the solution with Jigar's approach which I marked as accepted answer.

struts.xml:

<action name="search" class="com.mypackage.action.SearchAction">
    <result>/search-result.jsp</result>
    <result name="input">${url}</result>
</action>

I removed the type="redirect" because the fielderror message disappeared. I believe that is the expected behavior as documented in Apache docs:

Redirect Result

The response is told to redirect the browser to the specified location (a new request from the client). The consequence of doing this means that the action (action instance, action errors, field errors, etc) that was just executed is lost and no longer available.

Source: http://struts.apache.org/release/2.1.x/docs/redirect-result.html

SearchAction:

public class SearchAction extends ActionSupport implements RequestAware, Message {

    private String url;

    public String getUrl() {
        return url;
    }

    @Override
    public String execute() throws Exception {
        // business logic
        request.put("searchResults", searchResults);

        return SUCCESS;
    }

    @Override
    public void validate() {
        url = ServletActionContext.getRequest().getHeader("referer")
            .replace("http://localhost:8080/mysite/", ""); // get resource name only

        if(!url.contains(".jsp")) {
            url = "index.jsp"; // default page
        }           

        if(searchWord.length() == 0) {
            addFieldError("searchWord", BLANK_SEARCH);
        }
    }
}

Output:

enter image description here

It now stays on the current page on error.

Upvotes: 2

Roman C
Roman C

Reputation: 1

The current page you can get via servlet request. Create interceptor for intercepting a current page

public class CurrentPageInterceptor extends AbstractInterceptor {

  @Override
  public String intercept(ActionInvocation actionInvocation) throws Exception {
    HttpServletRequest request = ServletActionContext.getRequest();
    Map<String, Object> session = actionInvocation.getInvocationContext().getSession();
    String queryString = request.getQueryString();
    String savedUrl = request.getRequestURI()+(queryString==null?"":("?"+queryString));
    String currentPage = (String) session.get("savedUrl");
    if(currentPage == null) currentPage = savedUrl;
    session.put("currentPage", currentPage); 
    session.put("savedUrl", savedUrl);
    return actionInvocation.invoke();
  }
}

Registering interceptor in the parent package

<interceptors>
  <interceptor name="currentPage" class="com.company.interceptor.CurrentPageInterceptor"/>
  <interceptor-stack name="curentPageStack">
    <interceptor-ref name="currentPage"/>
    <interceptor-ref name="defaultStack"/>
  </interceptor-stack>
</interceptors>

<default-interceptor-ref name="curentPageStack"/>

Add a result to return a dynamic parameter

@Results({
  @Result(name = "input", type = "redirect", location = "${currentPage}"),
  @Result(location= "/search-result.jsp")
})
public class SearchAction extends ActionSupport implements RequestAware, SessionAware, Message {

private String currentPage;
//getter

   @Override
    public String execute() throws Exception {
        if (hasErrors()){
          currentPage = (String) session.get("currentPage");
          return "input";
        }


        // business logic
        request.put("searchResults", searchResults);

        return SUCCESS;
    }

    ...
}

Upvotes: 2

Jigar Mistry
Jigar Mistry

Reputation: 372

You can get the current page name using following code:

String actionName = ServletActionContext.getRequest().getHeader("Referer");

In Struts.xml, use a dynamic result such as:

<result name="input" type="redirect">${url}</result>

In the action, use getter method for url. By default set the value of url as "index.jsp". If you want to change it, set appropriate value for url. Like login.jsp etc.

Upvotes: 2

Related Questions