FemtoWeb/Resolutions

From LoadingByte Wiki
Jump to navigation Jump to search

Any action class (both plain and supported implementations) contains a method for executing the action. In all cases, that method must return another action for concluding the request. Such "concluding actions" are also called "resolutions". They are executed directly after the execution of your action has finished. An example might be a resolution which displays a JSP.

Null resolution

It is possible to just return null as a resulution. In that case, no further actions are executed. However, there are practically no cases where you want to do that.

View resolution

The com.quartercode.femtoweb.api.resolutions.View resolution sends a specific dynamic resource (in most cases a JSP) to the user. Internally, this action forwards the request to that resource. Therefore, all pushed request attributes, session attributes etc. are also forwarded to the resource. If the forwarding target is a JSP, they can then be accessed through EL. This behavior has already been shown in the section about attribute pushing.

Let's imagine the following file tree inside the dynamic asset folder (by default /WEB-INF/dynamic):

dynamic/
    index.jsp
    products/
        display.jsp
    users/
        login.jsp

Now, lets image that an action {actionBasePackage}.products.OverviewAction exists (it doesn't use ActionSupport for simplicity). Of course, the naming makes no sense in this case; it is, however, deliberately chosen to demonstrate how the second constructor works.

There are two constructors available for the view resolution. The first one just takes a path relative to the dynamic asset path and forwards the request to that path. Say we want to forward the request to login.jsp. The corresponding action would look like this:

public class OverviewAction implements Action {

    @Override
    public Action execute(HttpServletRequest request, HttpServletResponse response, Context context) throws Exception {

        // Do stuff ...

        return new View("users/login.jsp");
    }

}

However, it makes lots of sense to reflect the action package structure in the dynamic asset folder structure. Such an organization drastically increases maintainability. Say our overview action wants to render display.jsp. Because that page is located in the subfolder /products and the overview action is mapped to the URI /products/overview, the following code displays display.jsp without you having to worry about relative paths:

public class OverviewAction implements Action {

    @Override
    public Action execute(HttpServletRequest request, HttpServletResponse response, Context context) throws Exception {

        // Do stuff ...

        return new View(getClass(), "display.jsp");
    }

}

Redirect resolution

The com.quartercode.femtoweb.api.resolutions.Redirect resolution redirects the user's browser to another URI using HTTP 302. Therefore, all pushed request attributes and parameters will be lost, while session attributes are kept.

There are two constructors available for the redirect resolution. The first one just redirects the user to the set URL. See the JavaDoc of this JEE method for more details on the exact format the URL must have. This method is only recommended for redirecting to another website (e.g. http://quartercode.com):

public class XyzAction implements Action {

    @Override
    public Action execute(HttpServletRequest request, HttpServletResponse response, Context context) throws Exception {

        // Do stuff ...

        return new Redirect("http://quartercode.com");
    }

}

For redirecting to another action, you can use the second constructor. Internally, the user is redirected to the URI the action is mapped to. However, you as a programmer don't have to worry about any of that background stuff. Instead, you just set to which action the user should be redirected to:

public class XyzAction implements Action {

    @Override
    public Action execute(HttpServletRequest request, HttpServletResponse response, Context context) throws Exception {

        // Do stuff ...

        return new Redirect(TargetAction.class);
    }

}

Appending GET Parameters

Both constructors support attaching GET parameters to the redirect URL. Those parameters can be optionally added using the "parameters" vararg both constructors offer. That vararg takes an alternating array of GET parameter names and values and appends them to the redirect URL.

For example, the following call:

return new Redirect(SearchAction.class, "query", "amazing", "maxResults", 50);

would result in the URI /path/to/search?query=amazing&maxResults=50. If the vararg is empty, nothing (not even ?) is appended to the URL.

Custom resolutions

It is very simple to create custom resolutions. You just have to create a new action which does its job as soon as it's executed. The following example resolution just writes a set output string to the response.

public class StringOutputRedirect implements Action {

    private final String output;

    public StringOutputRedirect(String output) {

        this.output = output;
    }

    @Override
    public Action execute(HttpServletRequest request, HttpServletResponse response, Context context) throws IOException, ServletException {

        // Write the output string
        response.getWriter().println(output);

        // No further resolution
        return null;
    }

}

Because resolutions are just regular actions, they also need to return another resolution. In theory, this resolution chain could continue with another action but null. However, there are practically no uses for this "feature".