Configuration

JSmart uses a XML file for all configuration needed to setup the application. The webConfig.xml file must be provided and placed inside WEB-INF folder of your web project.

Basic configuration

The minimum XML configuration required for a project looks like the following. In case you want to check the entire configuration go to next section.

<?xml version="1.0" encoding="UTF-8"?>
<web-config>
    <package-scan>com.my.pckg</package-scan>

    <session-timeout>30</session-timeout>

    <welcome-url>/welcome</welcome-url>

    <url-patterns>
        <url-pattern>/welcome</url-pattern>
    </url-patterns>

    <message-files>
        <message-file>texts</message-file>
    </message-files>

    <default-locale>en</default-locale>
</web-config>

Complete configuration

The complete XML configuration for a project looks like the following:

<?xml version="1.0" encoding="UTF-8"?>
<web-config>

    <!-- Comma separated values to specify the packages to be scanned by the Framework for
         dependency injection and beans creation. -->
    <package-scan>com.my.pckg,com.my.repo</package-scan>

    <!-- Specify the lookup context for searching Enterprise Java Beans (EJBs) on application
         container for dependency injection.
         Values allowed are [global, app, module]. -->
    <ejb-lookup>module</ejb-lookup>

    <!-- Specify for how long (minutes) the session should be kept alive before the session
         is closed. The timeout is considered after last request is made to server. -->
    <session-timeout>30</session-timeout>

    <!-- Specify your secret key used to encrypt expressions on JSP page so your bean and
         method names are not exposed on HTML. -->
    <tag-secret-key>l2KWkQS0eIdTz5UX</tag-secret-key>

    <!-- Specify the URL to redirect request when context URL is accessed directly.
         Also this URL must be declared as url-pattern. -->
    <welcome-url>/welcome</welcome-url>

    <!-- Specify the URL for searching for Images, CSS and JS.
         In case it is specified, you must provide the JSmart CSS and JS at the URL. Please
         refer to Download page for downloading assets and more details. -->
    <assets-url>http://my.assets.store.com</assets-url>

    <!-- For automatic mapping, the JSP files must have the same name as the url-pattern,
         for example the url-pattern "/mypage" must have the respective file "mypage.jsp"
         so the final URL endpoint will be shown as "/mypage".
         In case the JSP file name does not match the url-pattern name, you must provide the
         relative path for the JSP file. -->
    <url-patterns>
        <url-pattern>/welcome</url-pattern>
        <url-pattern>/login</url-pattern>

        <!-- Error pages also must be specified as url-pattern -->
        <url-pattern>/error</url-pattern>
        <url-pattern>/not-found</url-pattern>
        <url-pattern>/forbidden</url-pattern>

        <!-- For dynamic paths use the wildcard /* at the end of your url-pattern -->
        <url-pattern>/dynamic/*</url-pattern>

        <!-- Example of non-matching url-pattern with JSP file name -->
        <url-pattern jsp="/WEB-INF/pages/user_reg.jsp">/register</url-pattern>

        <!-- The access attribute on url-pattern specifies that only authenticated users
             with specific roles (comma separated values) are able to access this URL.
             The wildcard (*) means that only authenticated user can access the URL regardless
             the authorization roles. -->
        <url-pattern access="*">/home</url-pattern>
        <url-pattern access="admin,technician">/restricted</url-pattern>

        <!-- The attribute loggedAccess on url-pattern specifies that authenticated users
             with specific roles are not able access this URL. -->
        <url-pattern access="*" loggedAccess="false">/not-restricted</url-pattern>
    </url-patterns>

    <!-- Map the HTTP codes to pages being used to provide error pages when specific HTTP code
         is generated from server while request is being processed.
         Also this URLs must be declared as url-pattern. -->
    <error-pages>
        <error-page code="403">/forbidden</error-page>
        <error-page code="404">/not-found</error-page>
        <error-page code="500">/error</error-page>
    </error-pages>

    <!-- Specify the security level of HTTP methods for the application container
         including the transport type and roles allowed for the specified HTTP method. -->
    <secure-methods>

        <!-- The transport attribute specifies the transport used for this HTTP method.
             Possible values are [none, confidential].
             The and emptyRole attribute specifies if users on container without permissions
             can access URLs using this HTTP method. Possible values are [deny, permit] -->
        <secure-method transport="none" emptyRole="permit">GET</secure-method>
        <secure-method transport="none" emptyRole="permit">POST</secure-method>
    </secure-methods>

    <!-- Specify text properties files located inside resources folder which
         will be automatically managed by the Framework to provide internationalized texts
         according to the clients locale following the standard i18n.
         For instance, the resource file at resources/mytexts_en_US.properties must be
         set as following. -->
    <message-files>
        <message-file>mytexts</message-file>
    </message-files>

    <!-- Specify the default locale to be used in case the current client locale is not mapped
         to any message-file resource. -->
    <default-locale>en</default-locale>

    <!-- Specify initial parameters for ServletContext when the application is initiated. -->
    <init-params>

        <!-- Example of key and value for initial parameter. -->
        <init-param name="paramName">parameterValue</init-param>
    </init-params>

    <!-- Specify the configuration for file upload through the Framework via MultiPartConfig
         on Servlet 3.0.
         So you can specify the maximum file size, maximum size of the request allowed for
         sending files.
         The file size threshold is used to specify the threshold to be used to get the stream
         written on disk in the specified folder.
         Check MultiPartConfig for more details. -->
    <upload-config maxFileSize="20848820" maxRequestSize="418018841" fileSizeThreshold="1048576">
        /tmp
    </upload-config>

    <!-- Specify the cache control to be sent on the response header to the client.
         This option allows the expire timeout control of contents based on its extension such as
         CSS, JavaScript or image files. -->
    <cache-patterns>
        <cache-pattern cacheControl="private" maxAge="604800" files="css,js,png" />
    </cache-patterns>

    <!-- Specify the encode format to be used to encode the response stream for the specified
         file mime types.
         The encode attribute accepts the possible values [gzip, deflate, gzip/deflate].
         The mimeTypes attribute accept a list (comma separated values) of myme types for applying
         the encoding. -->
    <content-encode encode="gzip/deflate"
                    mimeTypes="text/html,text/css,application/javascript,image/png" />

    <!-- Specify the static file extensions to be versioned, so we enforce the browser cache
         refresh when the system is deployed by adding the specified attribute version value
         as query parameter on the static file link. -->
    <file-versions>
        <file-version version="v101" extensions="css,js" excludeFolders="anyfoder1,anyfolder2" />
    </file-versions>

    <!-- Specify the escape behaviour over the request parameters sent to application.
         Default value is true, but if set as false the escape will not apply to request
         content sent to server. This is at your own risk ;) -->
    <escape-request>true</escape-request>

    <!-- Specify if the the generated HTML will be compressed before sending to the client. -->
    <compress-html>true</compress-html>

    <!-- Specify if the generated HTML shall be printed on server console before sending to
         the client, for debug purpose -->
    <print-html>true</print-html>

</web-config>

WebBean

WebBean is an annotation for Java classes used to handle Request actions and also responsible to provide dynamic content to your JSP pages. To map a class as WebBean you must annotate the class with @WebBean also the the class must be present inside the same package hierarchy declared in your package-scan configuration on webConfig.xml.

The mapped class will be called during request phase in case the JSP page requested contains any component with its attribute holding any expression referencing the bean by its name such as @{myBean.doAction}.

Basic WebBean

If you are searching for basic example to provide dynamic content to your JSP page, have a look on the following example with basic WebBean. Remember that the page should contain any component with its attribute mapping the bean via expression such as @{myBean.attr}. Check Components for more details.

package com.my.pckg;

import com.jsmartframework.web.annotation.WebBean;

@WebBean
public class MyBean {

    private String attr;

    /** The value is used to be sent to client when HTML page is being generated */
    public String getAttr() {
        return attr;
    }

    /** The value is set when the request is being processed and after this bean is constructed */
    public void setAttr(String attr) {
        this.attr = attr;
    }
}

Components with WebBean

If you are searching for an example on how to integrate select, checkbox, checkgroup or radiogroup with WebBean, please have a look on the following example. For those components declaration on JSP page, please check Components for more details.

package com.my.pckg;

import com.jsmartframework.web.annotation.WebBean;

@WebBean
public class MyBean {

    private String attr;

    /** Attribute to hold checkbox check */
    private boolean checkbox;

    /** Attribute to hold option selected */
    private String optionSelected;

    /** Attribute to hold checkgroup items selected */
    private List<Integer> checkgroupSelection;

    /** Attribute to hold radiogroup item selected */
    private String radiogroupSelected;

    /** The value is used to be sent to client when HTML page is being generated */
    public String getAttr() {
        return attr;
    }

    /** The value is set when the request is being processed and after this bean is constructed */
    public void setAttr(String attr) {
        this.attr = attr;
    }

    public boolean isCheckbox() {
        return checkbox;
    }

    public void setCheckbox(String checkbox) {
        this.checkbox = checkbox;
    }

    /**
     * Getter to provide options for select component that requires Map collection in which the
     * Map key is used as option value and the Map value is used as option text.
     */
    public Map<String, String> getSelectOptions() {

    }

    public String getOptionSelected() {
        return optionSelected;
    }

    public void setOptionSelected(String optionSelected) {
        this.optionSelected = optionSelected;
    }

    /**
     * Getter to provide items for checkgroup component that requires Map collection in which the
     * Map key is used as item value and the Map value is used as item label.
     */
    public Map<Integer, String> getCheckgroupItems() {

    }

    public List<Integer> getCheckgroupSelection() {
        return checkgroupSelection;
    }

    public void setCheckgroupSelection(List<Integer> checkgroupSelection) {
        this.checkgroupSelection = checkgroupSelection;
    }

    /**
     * Getter to provide items for radiogroup component that requires Map collection in which the
     * Map key is used as item value and the Map value is used as item label.
     */
    public Map<String, String> getRadiogroupItems() {

    }

    public String getRadiogroupSelected() {
        return radiogroupSelected;
    }

    public void setRadiogroupSelected(String radiogroupSelected) {
        this.radiogroupSelected = radiogroupSelected;
    }
}

Dynamic path on WebBean

If you are searching for an example on how to work with dynamic paths, please have a look on the following example. For more details about url-pattern mapping for dynamic URLs please refer to Complete Configuration section.

package com.my.pckg;

import com.jsmartframework.web.annotation.WebBean;
import com.jsmartframework.web.manager.WebContext;

/**
 * For dynamic path to work you need to map the url-pattern on webConfig.xml as
 * following example <url-pattern>/dynamic/*</url-pattern>
 */
@WebBean
public class MyBean {

    private String pathInfo;

    PostConstruct
    public void init() {
        pathInfo = WebContext.getRequest().getPathInfo();

        if (pathInfo == null || pathInfo.isEmpty()) {
            pathInfo = "/any_path_you_want";
            WebContext.redirectTo("/dynamic" + pathInfo);
        }
    }

    public void doAction() {
        // This action is triggered by button, link or ajax components when mapped as
        // @{myBean.doAction} on page related to the mapped dynamic path
    }

}

Action on WebBean

Have a look on the following example on how to use annotation to expose action methods in your WebBean to be integrated with your components, improve code readability and promote the re-usage of action methods.

package com.my.pckg;

import com.jsmartframework.web.annotation.Action;
import com.jsmartframework.web.annotation.WebBean;
import com.jsmartframework.web.manager.WebContext;

/**
 * For defining action methods on WebBean mapped on action components such as button, link,
 * ajax or dropaction components you simply need to annotate the method with @Action and
 * specify the component ids which the action will be applied, so you do not need to include
 * the action attribute on component tag at JSP level.
 */
@WebBean
public class MyBean {

    /**
     * The Action annotation accepts the following attributes:
     *
     * forIds - list of component ids which the action will be mapped on.
     *
     * ajax - specify if the action will be performed via Ajax or regular submit (Default true).
     *
     * event - specify the event to trigger the action in case ajax true and action
     *    bound to component other than button or link.
     *
     * timeout - specifies the timeout in milliseconds to wait before Ajax request is performed.
     *
     * onForm - specify the form to apply this action on so all input values present on
     *    form will be carried on request.
     *
     * update - list of component ids to be updated after action succeed. Only works
     *    if the return content is HTML, otherwise the update will not apply.
     *
     * beforeSend - list of JavaScript functions to be called before the Ajax request is
     *    made to server, the function may receive parameters such as jqXHR(XmlHttpRequest)
     *    and settings(Object).
     *    For more details, check http://api.jquery.com/jquery.ajax
     *
     * onSuccess - list of JavaScript functions to be called if the Ajax request returns
     *    successfully from server, the function may receive parameters such as data(Object),
     *    textStatus(String) and jqXHR(XmlHttpRequest).
     *    For more details, check http://api.jquery.com/jquery.ajax
     *
     * onError - list of JavaScript functions to be called if the Ajax request returns error
     *    from server, the function may receive parameters such as jqXHR(XmlHttpRequest),
     *    textStatus(String) and error(Error).
     *    For more details, check http://api.jquery.com/jquery.ajax
     *
     * onComplete - list of JavaScript functions to be called when the Ajax request completes
     *    regardless error or success, The function may receive parameters such as
     *    jqXHR(XmlHttpRequest) and textStatus(String).
     *    For more details, check http://api.jquery.com/jquery.ajax
     */
    @Action(forIds = "my-btn-id")
    public void doAction() {

        // This action is triggered by button, link, dropaction or ajax components when the
        // component id match one of the ids provided on annotation attribute.
    }

    @Action(forIds = "my-btn-one-id", update = {"component-one-id", "component-two-id"},
            onSuccess = "onActionSuccessFn")
    public void doActionOne() {

        // In this case the components specified via update attribute will be updated
        // when response is generated and after the success callback will be called
        // if there is no error with the request.
    }

    @Action(forIds = {"my-btn-two-id", "my-btn-three-id"}, beforeSend = "beforeActionFn",
            onError = "onActionErrorFn", onSuccess = "onActionSuccessFn")
    public void doActionTwo() {

        // In this case you are writing the response directly, so you have to deal with this
        // response using the callbacks defined on annotation.
        WebContext.writeResponseAsJson(myObject);
    }

    @Action(forIds = "my-component-id", event = "blur", onForm = "my-form-id",
            beforeSend = {"beforeActionFnOne", "beforeActionFnTwo"},
            onError = {"onActionErrorFnOne", "onActionErrorFnTwo"},
            onSuccess = {"onActionSuccessFnOne", "onActionSuccessFnTwo"},
            onComplete = {"onActionCompleteFnOne", "onActionCompleteFnTwo"})
    public void doActionThree() {

        // In this case your are defining the action for a component to trigger Ajax
        // request when the specified event happens, and also by informing the form id
        // all element values inside this form will be carried along with the request
        // and those values mapped on WebBean via component tag will be set when
        // executing the request on server side.
    }

}

Function on WebBean

Have a look on the following example on how to use annotation to expose JavaScript functions for pages which are integrated with WebBean methods to expose actions via mapped functions, so you will improve code readability and promote the re-usage of functions.

package com.my.pckg;

import com.jsmartframework.web.annotation.Arg;
import com.jsmartframework.web.annotation.Function;
import com.jsmartframework.web.annotation.WebBean;
import com.jsmartframework.web.manager.WebContext;

/**
 * For defining methods on WebBean to be mapped on JavaScript as functions you simply need to
 * annotate the method with @Function, specify the function name and the url-patterns in which
 * this function will be applied, so you do not need to include the function component tag at
 * JSP level.
 */
@WebBean
public class MyBean {

    /**
     * The Function annotation accepts the following attributes:
     *
     * name - name of JavaScript function to be invoked on client side. If not present the method
     *    name is used.
     *
     * forPaths - list of url-pattern which the JavaScript function will be mapped to direct requests
     *    to WebBean methods
     *
     * timeout - specifies the timeout in milliseconds to wait before Ajax request is performed.
     *
     * update - list of component ids to be updated after function call succeed. Only works
     *    if the return content is HTML, otherwise the update will not apply.
     *
     * beforeSend - list of JavaScript functions to be called before the Ajax request is
     *    made to server, the function may receive parameters such as jqXHR(XmlHttpRequest)
     *    and settings(Object).
     *    For more details, check http://api.jquery.com/jquery.ajax
     *
     * onSuccess - list of JavaScript functions to be called if the Ajax request returns
     *    successfully from server, the function may receive parameters such as data(Object),
     *    textStatus(String) and jqXHR(XmlHttpRequest).
     *    For more details, check http://api.jquery.com/jquery.ajax
     *
     * onError - list of JavaScript functions to be called if the Ajax request returns error
     *    from server, the function may receive parameters such as jqXHR(XmlHttpRequest),
     *    textStatus(String) and error(Error).
     *    For more details, check http://api.jquery.com/jquery.ajax
     *
     * onComplete - list of JavaScript functions to be called when the Ajax request completes
     *    regardless error or success, The function may receive parameters such as
     *    jqXHR(XmlHttpRequest) and textStatus(String).
     *    For more details, check http://api.jquery.com/jquery.ajax
     */
    @Function(forPaths = "/any_path_you_want")
    public void myFunction() {

        // This method is triggered by calling the method name via JavaScript.
    }

    @Function(forPaths = "/any_path_you_want",
              update = {"component-one-id", "component-two-id"}, onSuccess = "onFunctionSuccess")
    public void myFunctionOne() {

        // In this case the components specified via update attribute will be updated
        // when response is generated and after the success callback will be called
        // if there is no error with the request.
    }

    @Function(forPaths = "/any_path_you_want", beforeSend = "beforeFunction",
              onError = "onFunctionError", onSuccess = "onFunctionSuccess")
    public void myFunctionTwo() {

        // In this case you are writing the response directly, so you have to deal with this
        // response using the callbacks defined on annotation.
        WebContext.writeResponseAsJson(myObject);
    }

    @Function(name = "customFunction", forPaths = "/any_path_you_want")
    public void myFunctionThree(@Arg String argOne, @Arg String argTwo) {

        // This method is triggered by calling the function name via JavaScript and
        // passing arguments such as myFunctionThree('myArgOne', 'myArgTwo');
        // In case you call the function with less arguments this method still be called
        // but the arguments will empty, such as calling on JavaScript myFunctionThree();
    }

    @Function(forPaths = "/any_path_you_want")
    public void myFunctionFour(@Arg(bindTo = "any-input-id") String argOne) {

        // This method is triggered by calling the method name via JavaScript
        // without passing any argument, so by specifying bindTo as page element id,
        // the framework will capture the value of specified component and carry it
        // along with the request as method argument.
    }

    @Function(forPaths = "/any_path_you_want")
    public void myFunctionWithJsonToObjectAdapter(@Arg MyObjectAdapter objectAdapter) {

        // This method is triggered by calling the method name via JavaScript
        // passing JSON object as argument, so the framework will capture the JSON
        // as String and convert it to the specified object on argument.
        // Make sure the object holds the same field names as the properties sent
        // on JSON object once the framework uses Gson to convert it.
    }

}

More about WebBean

Have a look on the following example with complete explanation on how to use your bean along with integrated Frameworks.

package com.my.pckg;

import com.jsmartframework.web.annotation.ScopeType;
import com.jsmartframework.web.annotation.WebBean;
import com.jsmartframework.web.annotation.PreSet;
import com.jsmartframework.web.annotation.QueryParam;
import com.jsmartframework.web.annotation.PreAction;
import com.jsmartframework.web.annotation.PostAction;
import com.jsmartframework.web.annotation.ExecuteAccess;
import com.jsmartframework.web.annotation.Unescape;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;

import javax.ejb.EJB;
import javax.inject.Inject;

/**
 * The WebBean annotation accepts the following attributes:
 *
 * name - specifies the name for mapping this class on JSP pages. If not specified the class name
 *    is used in camelcase.
 *
 * scope - specifies the scope of this class instance, with the possible values:
 *    Request: (Default): this class instance will be kept on server for the life cycle of the request.
 *    Session: this instance will be kept on server for the life cycle of the session.
 *    Application: this instance will be kept on server for the entire life cycle of the application.
 */
@WebBean(name = "myBean", scope = ScopeType.SESSION)
public class MyBean {

    /** Spring context objects can be automatically injected using following Spring annotation */
    @Autowired
    private SpringService springService;

    /** Spring properties values mapped on its context can be injected using Spring annotation */
    @Value("${my.property.key}")
    private String propertyValue;

    /** Enterprise Java Beans are lookup on application container and injected using the EJB */
    @EJB
    private EjbService ejbService;

    /** Other WebBeans present in same request can be injected by using Inject annotation */
    @Inject
    private AuthBean authBean;

    @Inject
    private AnotherBean anotherBean;

    private String attr;

    /** In case you require a value to be available when handling PostConstruct method */
    @PreSet
    private String attrTwo;

    /**
     * In case you need to retrieve URL param when processing the request, but keep in mind
     * that it only accepts String value.
     */
    @QueryParam("paramName")
    private String queryParam;

    /**
     * In case you need to expose the attribute value to JavaScript in the page where this
     * bean is mapped, just annotate your attribute with @ExposeVar.
     * To retrieve the value on JavaScript just call JSmart.getExposeVar('exposeAttr'), for more
     * details refer to JavaScript page.
     */
    @ExposeVar
    private String exposeAttr;

    @PostConstruct
    public void init() {
        // This method is called after instance is created and all dependencies are injected.
    }

    @PreDestroy
    public void destroy() {
        // This method is called before instance is destroyed and removed from its scope
    }

    @PreAction(onActions = {"doAction"})
    public boolean preAction() {
        // This method is called before action is executed and allow boolean return to indicate if
        // action must be executed. Return true to execute the action or false otherwise.

        // This method is also called before annotated @Action methods mapped by its name.
        return true;
    }

    public void doAction() {
        // This action is triggered by button, link or ajax components when mapped as
        // @{myBean.doAction}
    }

    @PostAction(onActions = {"doAction"})
    public void postAction() {
        // This method is called after doAction is executed

        // This method is also called after annotated @Action methods mapped by its name.
    }

    public String doRedirect() {
        // This action is triggered by button, link or ajax components when mapped as
        // @{myBean.doRedirect}.
        // By returning a relative path string the page is automatically redirected
        return "/path";
    }

    @ExecuteAccess(access = {"roleOne", "roleTwo"})
    public void doRestrictedAction() {
        // In case you want to ensure that this action is only executed by authenticated users with
        // specific access roles. Use @ExecuteAccess annotation and specify the list of
        // roles allowed to execute this method.
    }

    public String getAttr() {
        return attr;
    }

    @Unescape
    public void setAttr(String attr) {
        // In case you need to get this information unescaped from request. This is at your own risk ;)
        this.attr = attr;
    }

    public String getAttrTwo() {
        return attrTwo;
    }

    public void setAttrTwo(String attrTwo) {
        this.attrTwo = attrTwo;
    }
}

AuthBean

AuthBean is an annotation for Java classes used to authenticate request and guarantee authorized access to pages which requires user to be authenticated and/or hold specific authorization access roles. To map a class as AuthBean you must annotate the class with @AuthBean and specify the required fields loginPath and homePath.

Authenticating

JSmart uses class annotation to map authenticate bean and field and method annotations for checking if the authentication succeed. By doing so, the AuthBean comes into two flavors which can use Request or Session authentication mechanism.

For Request mechanism you are required provide secretKey as part of @AuthBean annotation to be used to encrypt field values annotated with @AuthField once those will be set as cookies when the authentication succeed.

For Session mechanism you are required to implement Serializable interface once your entire bean will be stored on session.

In addition the class must be present inside the same package hierarchy declared in your package-scan tag on webConfig.xml. Have a look in the following example:

package com.my.pckg;

import com.jsmartframework.web.annotation.AuthBean;
import com.jsmartframework.web.annotation.AuthField;
import com.jsmartframework.web.annotation.AuthMethod;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;

import javax.ejb.EJB;

/**
 * The AuthBean annotation accepts the following attributes:
 *
 * name - specifies the name for mapping this class on JSP pages. If not specified the class
 *    name is used in camel case.
 *
 * type - specify the type of authentication mechanism, with the possible values:
 *    Request: (Default) the authentication relies on AuthField values which are encrypted and
 *             stored as cookies on client side.
 *    Session: the authentication mechanism relies on Session so the entire bean is stored
 *             on server session.
 *
 * loginPath - specifies the page to redirect request case unauthenticated access is made to
 *    restricted pages mapped on url-pattern tag on webConfig.xml.
 *
 * homePath - specifies the page to redirect request case login authentication succeed or
 *    further access is done on loginPath with user already authenticated.
 *
 * secretKey - specifies the key to be used for encryption of the AuthField value set as
 *    cookies case the authentication mechanism is of type Request.
 */
@AuthBean(name = "myAuthBean", loginPath = "/login", homePath = "/home", secretKey = "")
public class MyAuthBean implements Serializable {

    /** Spring context objects can be automatically injected using following Spring annotation */
    @Autowired
    private SpringService springService;

    /** Spring properties values mapped on its context can be injected using Spring annotation */
    @Value("${my.property.key}")
    private String propertyValue;

    /** Enterprise Java Beans are lookup on application container and injected using the EJB */
    @EJB
    private EjbService ejbService;

    /**
     * Include this field on authentication control. While this field remains null the
     * user is not authenticated, so any access to restricted pages will be refused and
     * redirected to specified loginPath.
     */
    @AuthField("email")
    private String email;

    @AuthField("uuid")
    private String uuid;

    /** Provide list of roles to manage authorization on application via authorize component */
    @AuthAccess
    private List authRoles;

    /**
     * This method is invoked per request to check if AuthFields provided are valid.
     * Keep in mind that the AuthField values can be null in case they are not set yet
     * as cookies for Request authentication mechanism.
     */
    @AuthMethod
    public boolean isAuthenticated() {
         // Here you can use the AuthField to search if those credentials are valid on database
         // or whatever cache mechanism you are using.

         // Return true if the request is authenticated or false otherwise. In case false the
         // user will redirected to login page specified on loginPath.
         return uuid != null && email != null;
    }

    public String doLogin(String email, String password) {
        // General action method to authenticate user credentials. This action can be triggered
        // by button, link or ajax components when mapped as @{myAuthBean.doLogin} on JSP
        // page or called by any other WebBean managing login page.

        // In case authentication succeed you must assign fields annotated with @AuthField
        // and @AuthAccess

        // Returns any logged page desired otherwise return null
        return "/home";
    }
}

WebSecurity

WebSecurity is an annotation for Java classes used to provide more security for requests and guarantee valid access for POST requests which are meant to change state of your application. To map a class as WebSecurity you must annotate the class with @WebSecurity and implement the interface CsrfRequestListener to provide and validate token name and values for preventing CSRF (Cross-Site Request Forgery) attacks.

Securing your requests

To map a class as WebSecurity you must annotate the class with @WebSecurity and implement the interface CsrfRequestListener to provide and validate token name and values for preventing CSRF (Cross-Site Request Forgery) attacks. In addition the class must be present inside the same package hierarchy declared in your package-scan tag on webConfig.xml. Have a look in the following example:

package com.my.pckg;

import com.jsmartframework.web.adapter.CsrfAdapter;
import com.jsmartframework.web.annotation.WebSecurity;
import com.jsmartframework.web.listener.CsrfRequestListener;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;

import javax.ejb.EJB;
import javax.inject.Inject;

/**
 * The WebSecurity annotation is meant to work along with CsrfRequestListener interface
 * to provide one more option for request security and ensure that the requester is valid.
 *
 * By implementing the CsrfRequestListener you are able to provide token name and value
 * to prevent CSRF attacks.
 */
@WebSecurity
public class CsrfListener implements CsrfRequestListener {

    /** Spring context objects can be automatically injected using following Spring annotation */
    @Autowired
    private SpringService springService;

    /** Spring properties values mapped on its context can be injected using Spring annotation */
    @Value("${my.property.key}")
    private String propertyValue;

    /** Enterprise Java Beans are lookup on application container and injected using the EJB */
    @EJB
    private EjbService ejbService;

    @Inject
    private MyAuthBean authBean;

    /**
     * This method is called every time HTML page is generated and returned to the client, so you
     * can provide token name and value that will be stored on page only and those valus will be sent
     * along with the next action requests (POST) in order to ensure that it is not a CSRF attack.
     *
     * It is up to you how this token is generated, if per request or per number of requests or
     * even per session. Also you can decide how to store your tokens by using session or any
     * other cache mechanism.
     */
    @Override
    public CsrfAdapter generateToken() {
        return new CsrfAdapter("token_name", "token_value");
    }

    /**
     * This method is called per POST request so you can validate if the request contains
     * valid token name and value previously generated.
     * Return true if token name and value are valid, otherwise return false. By returning
     * false the HTTP 403 error status is returned on response.
     */
    @Override
    public boolean isValidToken(CsrfAdapter adapter) {
        return adapter.getName().equals("token_name") && adapter.getToken().equals("token_value");
    }
}

AsyncBean

AsyncBean is an annotation applied on Java classes used to handle asynchronous events sent from server to client for specified path, know as ServerPush in which the connection stays active between client and server but the thread from web container pool is released.

Using async events

JSmart uses class annotation to map asynchronous bean for specific path, so the class must be annotated with @AsyncBean and specify the path on annotation attribute, this path also must be declared as url-pattern tag and the class must be present inside the same package hierarchy declared in your package-scan tag on webConfig.xml. For one last requirement, the class must implement the interface WebAsyncListener. Have a look in the following example:

package com.my.pckg;

import com.jsmartframework.web.annotation.AsyncBean;
import com.jsmartframework.web.annotation.QueryParam;
import com.jsmartframework.web.listener.WebAsyncListener;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;

import javax.ejb.EJB;

@AsyncBean("/home/status")
public class MyAsync implements WebAsyncListener {

    /** Spring context objects can be automatically injected using following Spring annotation */
    @Autowired
    private SpringService springService;

    /** Spring properties values mapped on its context can be injected using Spring annotation */
    @Value("${my.property.key}")
    private String propertyValue;

    /** Enterprise Java Beans are lookup on application container and injected using the EJB */
    @EJB
    private EjbService ejbService;

    /** Other WebBeans present in same request can be injected by using Inject annotation */
    @Inject
    private AuthBean authBean;

    /**
     * In case you need to retrieve URL param when processing the request, but keep in mind
     * that it only accepts String value.
     */
    @QueryParam("paramName")
    private String queryParam;

    /** Control asynchronous looping for pushing events to client side */
    private volatile boolean finished;

    @Override
    public void asyncContextCreated(final AsyncContext asyncContext) {

        /** Set timeout in milliseconds for the asynchronous context expiration */
        asyncContext.setTimeout(10000);

        /** Start own thread to push events to client side */
        asyncContext.start(new Runnable() {
            @Override
            public void run() {
                while (!finished) {

                    // Generate events to be sent to client that must start the connection using
                    // HTML5 Server-Sent Events technique. For more details please visit the link.

                    // Write response as text/event-stream for the registered event
                    WebContext.writeResponseAsEventStream(asyncContext, "event-name", event);
                }
            }
        });
    }

    /**
     * The asynchronous context can be finished by couple of reasons as following:
     *
     * Complete - the asynchronous context was completed by container or explicitly
     * Timeout - the asynchronous context expired
     * Error - the asynchronous context found error while pushing events to client
     */
    @Override
    public void asyncContextDestroyed(AsyncContext asyncContext, Reason reason) {
        if (reason == Reason.TIMEOUT) {
            asyncContext.complete();
        }
        finished = true;
    }
}

RequestPath

RequestPath is an annotation for Java classes used to map specific resource path in order to handle requests via integration with Controller from Spring MVC. It is very useful case you want to integrate a REST API along with your application context and provide extra features for your page or external access.

Working with request paths

JSmart uses class annotation to map request path, so the class must be annotated with @RequestPath and specify the path on annotation attribute which must end with /*. The class must be present inside the same package hierarchy declared in your package-scan tag on webConfig.xml. Have a look in the following example:

package com.my.pckg;

import com.jsmartframework.web.annotation.RequestPath;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;

import java.io.IOException;

/**
 * The RequestPath annotation must have path attribute value ending with /* pattern and also
 * the class must be annotated with @Controller from Spring
 */
@Controller
@RequestPath("/v1/*")
public class MyController {

    /** Spring context objects can be injected using following Spring annotation */
    @Autowired
    private SpringService springService;

    /** Spring properties values mapped on its context can be injected using Spring annotation */
    @Value("${my.property.key}")
    private String propertyValue;

    /** The sub-resource request mapping must done via Spring MVC integration */
    @ResponseBody
    @RequestMapping(value = "/test", method = RequestMethod.GET)
    public void doGet() throws IOException {

        // Handle GET on resource /v1/test
    }
}

More Options

JSmart provides more options case you need to declare your own Servlet, Filter or Listener such as ServletContextListener, HttpSessionListener or ServletRequestListener.

Integrating WebServlet

To integrate WebServlet into your application you need to create a Java class that extends HttpServlet and must be annotated with @WebServlet from JSmart framework. The class must be present inside the same package hierarchy declared in your package-scan tag on webConfig.xml. Have a look in the following example:

package com.my.pckg;

import com.jsmartframework.web.annotation.WebServlet;

import java.io.IOException;

import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.ServletException;

@WebServlet(urlPatterns = {"/mypath"})
public class MyServlet extends HttpServlet {

    /** Spring context objects can be automatically injected using following Spring annotation */
    @Autowired
    private SpringService springService;

    /** Spring properties values mapped on its context can be injected using Spring annotation */
    @Value("${my.property.key}")
    private String propertyValue;

    /** Enterprise Java Beans are lookup on application container and injected using the EJB */
    @EJB
    private EjbService ejbService;

    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {

        // Handle GET request
    }
}

Integrating WebFilter

To integrate WebFilter into your application you need to create a Java class that implements Filter and must be annotated with @WebFilter from JSmart framework which have the capability to specify the order of the filter execution. The class must be present inside the same package hierarchy declared in your package-scan tag on webConfig.xml. Have a look in the following example:

package com.my.pckg;

import com.jsmartframework.web.annotation.WebFilter;

import java.io.IOException;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.ServletException;

@WebFilter(order = 1)
public class MyFilter implements Filter {

    /** Spring context objects can be injected using following Spring annotation */
    @Autowired
    private SpringService springService;

    /** Spring properties values mapped on its context can be injected using Spring annotation */
    @Value("${my.property.key}")
    private String propertyValue;

    /** Enterprise Java Beans are lookup on application container and injected using the EJB */
    @EJB
    private EjbService ejbService;

    @Override
    public void init(FilterConfig config) throws ServletException {

    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain)
            throws IOException, ServletException {
        filterChain.doFilter(request, response);
    }

    @Override
    public void destroy() {

    }
}

Integrating WebListener

To integrate WebListener into your application you need to create a Java class annotated with @WebListener from JSmart framework. In case your listener wants to receive servlet context events this class must implement ServletContextListener, for session events it must implement HttpSessionListener or for request events implement the interface ServletRequestListener. The class must be present inside the same package hierarchy declared in your package-scan tag on webConfig.xml. Have a look in the following example:

package com.my.pckg;

import com.jsmartframework.web.annotation.WebListener;

import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;

@WebListener
public class MyContextListener implements ServletContextListener {

    /** Spring context objects can be injected using following Spring annotation */
    @Autowired
    private SpringService springService;

    /** Spring properties values mapped on its context can be injected using Spring annotation */
    @Value("${my.property.key}")
    private String propertyValue;

    /** Enterprise Java Beans are lookup on application container and injected using the EJB */
    @EJB
    private EjbService ejbService;

    @Override
    public void contextInitialized(ServletContextEvent event) {

    }

    @Override
    public void contextDestroyed(ServletContextEvent event) {

    }
}
package com.my.pckg;

import com.jsmartframework.web.annotation.WebListener;

import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener;

@WebListener
public class MySessionListener implements HttpSessionListener {

    /** Spring context objects can be injected using following Spring annotation */
    @Autowired
    private SpringService springService;

    /** Spring properties values mapped on its context can be injected using Spring annotation */
    @Value("${my.property.key}")
    private String propertyValue;

    /** Enterprise Java Beans are lookup on application container and injected using the EJB */
    @EJB
    private EjbService ejbService;

    @Override
    public void sessionCreated(HttpSessionEvent event) {

    }

    @Override
    public void sessionDestroyed(HttpSessionEvent event) {

    }
}
package com.my.pckg;

import com.jsmartframework.web.annotation.WebListener;

import javax.servlet.ServletRequestEvent;
import javax.servlet.ServletRequestListener;

@WebListener
public class MyRequestListener implements ServletRequestListener {

    /** Spring context objects can be injected using following Spring annotation */
    @Autowired
    private SpringService springService;

    /** Spring properties values mapped on its context can be injected using Spring annotation */
    @Value("${my.property.key}")
    private String propertyValue;

    /** Enterprise Java Beans are lookup on application container and injected using the EJB */
    @EJB
    private EjbService ejbService;

    @Override
    public void requestInitialized(ServletRequestEvent event) {

    }

    @Override
    public void requestDestroyed(ServletRequestEvent event) {

    }
}

Utility Classes

JSmart provides a range of utility methods for handling request, response, internationalized texts, images and the interaction with client side via alerts. Also it can feature your WebBean case you need to integrate with Google ReCaptcha or respond with content other than HTML such as JSON, XML, file stream or event stream.

Providing more functionality

Have a look on the following example and check what utility classes can do for you.

package com.my.pckg;

import com.jsmartframework.web.annotation.WebBean;
import com.jsmartframework.web.manager.WebContext;
import com.jsmartframework.web.util.WebAlert;
import com.jsmartframework.web.util.WebText;
import com.jsmartframework.web.util.WebImage;

/**
 * All interaction with WebContext class only works on current thread, so DO NOT try to use
 * this utility class inside your own threads.
 */
@WebBean
public class MyBean {

    @PostConstruct
    public void init() {

        // After this method execution the page will be redirected to the path informed
        WebContext.redirectTo("/other_path");

        // After this method execution the new tab will opened with the redirect path informed
        WebContext.isRedirectToWindow("/other_path");
    }

    public void doWorkWithRequest() {

        // It returns the context from your application
        ServletContext servletContext = WebContext.getApplication();

        // It returns the current session from the request
        HttpSession session = WebContext.getSession();

        // It returns the current request being handled
        HttpServletRequest request = WebContext.getRequest();

        // It returns the current response being handled
        HttpServletResponse response = WebContext.getResponse();

        // Returns true if the current request being handled was originated from Ajax
        boolean isAjaxRequest = WebContext.isAjaxRequest();

        // Returns an attribute associated with your request. This method will look for attribute
        // presence on Request, than on Session and if not found it will search on Application
        Object attribute = WebContext.getAttribute("attribute_name");

        // It will check if attribute is present at least in one of the following objects:
        // HttpServletRequest, HttpSession or ServletContext
        boolean containAttr = WebContext.containsAttribute("attribute_name");

        // It returns all query parameters sent on URL for this request
        Map queryParams = WebContext.getQueryParams();

        // It returns the locale associated with current request
        Locale locale = WebContext.getLocale();
    }

    public void doWorkWithSession() {

        // This call will invalidate your current session. So use with caution ;)
        WebContext.invalidate();
    }

    public void doWorkWithRequestContent() {

        // In case your request contains a ReCaptcha parameter and you want to validate it on
        // server side use this method. You only need to inform the secret key for validation
        // the rest is done by JSmart :)
        boolean valid = WebContext.checkReCaptcha("your_secret_key");

        // It returns the string escaped based on JavaScript and HTML standards
        String escapedString = WebContext.escapeString("any_string");

        // It returns the string unescaped based on HTML and JavaScript standards
        String unescapedString = WebContext.unescapeString(escapedString);

        // It returns the request content as String
        String content = WebContext.getContentAsString();

        // In case you know that the content is JSON, you can convert it to a mapped class
        MyJsonAdapter jsonAdapter = WebContext.getContentFromJson(MyJsonAdapter.class);

        // In case you know that the content is XML, you can convert it to a mapped class
        MyXmlAdapter xmlAdapter = WebContext.getContentFromXml(MyXmlAdapter.class);
    }

    /**
     * The following methods are very useful when you want to return customized content other than
     * HTML, such as JSON, XML, File or Event stream. Note that by using those methods the page
     * will not be forwarded to be rendered using JSP standards.
     *
     * Also they are very useful when working with Ajax request once you can specify callback
     * functions for success and or error cases. Check Components for more details.
     */
    public void doWorkWithResponseContent() {

        // Use this method in case you want to return the response as String
        WebContext.writeResponseAsString("any_string");

        // Use this method in case you want to return the response as JSON, so you only need to
        // provide a adapter object which hold values to be converted to JSON
        WebContext.writeResponseAsJson(myJsonAdapter);

        // Use this method in case you want to return the response as XML, so you only need to
        // provide a adapter object which hold values to be converted to XML
        WebContext.writeResponseAsXml(myXmlAdapter);

        // Use this method in case you want to return the response as Event Stream for
        // asynchronous events. It is very useful when integrated with @AsyncBean to
        // provide events to client side
        WebContext.writeResponseAsEventStream(asyncContext, "event-name", dataObject);

        // Use this method in case you want to return the response as File Stream for download.
        // It is very useful when you want to integrate download in your page.
        WebContext.writeResponseAsFileStream(file, 2048);
    }

    public void doWorkWithAlertAndTexts() {

        // In case you need to retrieve internationalized message texts from properties mapped on
        // webConfig.xml you can use the following utility class. Remember to use the same name
        // you mapped on config file, such as "texts" for <message-file>texts</message-file>
        String textOne = WebText.getString("texts", "my.key.inside.properties.file");

        // You also can retrieve formatted texts from properties in case the properties value
        // contains format parameters such "{0}" or "%s", (not both).
        String textTwo = WebText.getString("texts", "my.key.properties.file", paramOne, paramTwo);

        // Use this method case you want to send alert to page about the request processing status.
        // For more details on how to setup the alert on JSP page check Components page.

        // You can send more than one message on same alert but keep in mind that the title,
        // icon and type of alert used will be defined by the first call to setup message on alert.
        WebContext.addInfo("alert-id-on-page", "Any info message");

        WebContext.addError("alert-id-on-page", "Any error message");

        WebContext.addWarning("alert-id-on-page", "Any warning message");

        WebContext.addSuccess("alert-id-on-page", "Any success message");

        // If you want to customize the alert with title, message and icon you can use the
        // following approach by setting up the entire WebAlert. Also the Bootstrap glyphicons
        // are already integrated on JSmart, so you only need to specify its name
        WebAlert alert = new WebAlert(WebAlert.AlertType.SUCCESS);
        alert.setTitle("Any title");
        alert.setTitleIcon("glyphicon-thumbs-up");
        alert.setMessage("Any message");

        WebContext.addAlert("alert-id-on-page", alert);
    }
}

Adapter Classes

JSmart have a different range of utility classes made to provide dynamic content by integration with some components such as table, list and carousel. For details on how to setup those componets check the Components page.

Adapters on WebBean

Have a look on the following example and check what you can provide from WebBean.

package com.my.pckg;

import com.jsmartframework.web.annotation.WebBean;
import com.jsmartframework.web.adapter.ListAdapter;
import com.jsmartframework.web.adapter.TableAdapter;
import com.jsmartframework.web.adapter.SlideAdapter;
import com.jsmartframework.web.adapter.HeaderAdapter;
import com.jsmartframework.web.adapter.ImageAdapter;

@WebBean
public class MyBean {

    /**
     * It provides a list of slides to be used for rendering the carousel on JSP page via
     * carousel component. In this component you must specify the values as @{myBean.mySlides}
     * so the framework will call this method during HTML page creation.
     */
    public List getMySlides() {
        List slides = new ArrayList<>();

        HeaderAdapter header = new HeaderAdapter();
        header.setTitle("Slide header");
        header.setIcon("glyphicon-fire");
        header.setType("h4");

        ImageAdapter image = new ImageAdapter("image.png", "css/images");

        SlideAdapter slideOne = new SlideAdapter();
        slideOne.setHeader(header);
        slideOne.setLabel("Any slide label");
        slideOne.setImage(image);
        slideOne.setActive(true);

        slides.add(slideOne);
        return slides;
    }

    /**
     * Returns a list of objects for table to be used to render scrollable table content.
     */
    private MyTableAdapter getMyTableAdapter() {
        return new MyTableAdapter();
    }

    /**
     * The abstract TableAdapter class must be extended to provide a list of objects for
     * appending on table following the criteria passed as method arguments as showed below.
     */
    private class MyTableAdapter extends TableAdapter {

        /**
         * Load content for table following the criteria for appending chunks of data to table.
         *
         * offsetIndex - index of last row element on table being scrolled or zero if no elements
         *
         * offset - object value of last row element on table being scrolled or null if no
         *    elements on table. This offset object is by default defined via object toString()
         *    or it can be specific object field case informed on scrollOffset table
         *    attribute.
         *
         * size - the size defined on table component for getting chunks oda data to render the table.
         *
         * sort - String to sort order of table. Possible values are ["asc","desc"]. Default to "asc".
         *
         * filters - Map as key containing the object field name and the map value containing the
         *    field value for filtering the content sent to page.
         */
        @Override
        public List load(int offsetIndex, Object offset, int size, String sort,
                                    int order, Map filters) {

        }
    }


    /**
     * Returns a list of objects for list to be used to render scrollable list content.
     */
    private MyListAdapter getMyListAdapter() {
        return new MyListAdapter();
    }

    /**
     * The abstract ListAdapter class must be extended to provide a list of objects for
     * appending on list following the criteria passed as method arguments as showed below.
     */
    private class MyListAdapter extends ListAdapter {

        /**
         * Load content for list following the criteria for appending chunks of data to list.
         *
         * offsetIndex - index of last row element on list being scrolled or zero if no elements
         *
         * offset - object value of last row element on list being scrolled or null if no
         *    elements on list. This offset object is by default defined via object toString()
         *    or it can be specific object field case informed on scrollOffset list attribute.
         *
         * size - the size defined on list component for getting chunks oda data to render the list.
         */
        @Override
        public List load(int offsetIndex, Object offset, int size) {

        }
    }
}