LastaFlute Action

URL Mapping

You can know the URL from the action name.

Mapping Convention (Big convention)

Request URL
Action class + Execute method

Mapping Example

ProfilePasswordAction#change()
/profile/password/change/
ProductAction#list()
/product/list/
ProductListAction#index()
/product/list/
MypageAction#index()
/mypage/
RootAction#index()
/ ※Special Action means URL '/'

Action Package

You can just know the location of action from the name.

Package Convention

Application Package
[your domain].app e.g. org.docksidestage.app
Web Package
[Application Root].web e.g. org.docksidestage.app.web
Action's Package
*you can use Action's prefix package

Package Example

You can choose several pattern like this: e.g. ProfilePasswordAction

  • [Application Root].web.ProfilePasswordAction#change()
  • [Application Root].web.profile.ProfilePasswordAction#change() *recommended
  • [Application Root].web.profile.password.ProfilePasswordAction#change()
e.g. Action Class Package Location @Directory
org.docksidestage
 |-app // Application Package
 |  |-logic
 |  |-web // Web Package
 |     |-product
 |     |  |-ProductListAction
 |     |  |-ProductPurchaseAction
 |     |-profile
 |     |  |-ProfilePasswordAction
 |     |  |-ProfileWithdrawalAction
 |     |-mypage
 |     |  |-MypageAction
 |     |-RootAction
 |-dbflute
 |  |-allcommon
 |  |-bsbhv
 |  |-...
 |-mylasta
 |  |-action
 |  |-direction
 |  |-...

make Action Class

arguments and return value for IN/OUT

Action Defintion

Super Class
extends [App]BaseAction
Behavior DI
instance variable with @Resource
Execute Method
public method with @Execute
e.g. Action Class Definition @Java
public class ProductListAction extends DocksideBaseAction { // Super Class

    @Resource
    private ProductBhv productBhv; // Behavior DI

    @Execute
    public HtmlResponse index() { // Execute Method
        ...
    }
}

URL Parameter

e.g. ProductListAction#index()

e.g. accept URL parameter as required argument @Java
    @Execute
    public HtmlResponse index(int pageNumber) { // /product/list/3
        ...
    }
e.g. accept URL parameter as optional argument @Java
    @Execute
    public HtmlResponse index(OptionalThing<Integer> pageNumber) {
        pageNumber.ifPresent(() -> { // /product/list/3
            ...
        }).orElse(() -> { // /product/list/
            ...
        });
    }
e.g. accept URL parameter with more URL @Java
    // /product/list/mystic/ikspiary/oneman/ (sea=mystic, land=oneman)
    @Execute(urlPattern = "{}/ikspiary/{}")
    public HtmlResponse index(String sea, String land) {
        ...
    }

Action Form (for POST, GET parameter)

e.g. accept POST parameter by action form @Java
    @Execute
    public HtmlResponse doSignin(ProductSearchForm form) { // POST (or also GET)
        ...
    }
e.g. both URL parameter and GET parameter @Java
    // e.g. /.../list/3?favoriteCode=sea&nextName=land
    @Execute
    public HtmlResponse index(int pageNumber, ProductSearchForm form) {
        ...
    }

You can use Validator Annotation for basic validation. e.g. Required, Max... (then you should call the validate() method in execute method of action)

e.g. validator annotation in form @Java
public class ProductEditForm {

    @Required
    public String productName;
}

And you can basic native type for bean properties. e.g. Integer, LocalDate, CDef...

e.g. native type for properties in form @Java
public class ProductSearchForm {

    public Integer productId;
    public String productName;
    public CDef.ProductStatus productStatus;
}

JSON Body (for JSON in request body)

e.g. accept JSON in request body by JSON body @Java
    @Execute
    public JsonResponse<ProductBean> index(ProductSearchBody body) {
        ...
    }

It can be treated as action form, e.g. can use validation, native type properties

e.g. body for product search @Java
public class ProductSearchBody {

    public Integer productId;
    public String productName;
    @Required
    public CDef.ProductStatus productStatus;
}

Action Response

HtmlResponse
asHtml(path_...) or redirect(...class)
JsonResponse
asJson(bean)
StreamResponse
asStream(ins)
e.g. HtmlResponse @Java
    @Execute
    public HtmlResponse index() {
        ...
        return asHtml(path_MyPage_MyPageJsp);
    }

    @Execute
    public HtmlResponse doUpdate() {
        ...
        return redirect(MypageAction.class);
    }
e.g. JsonResponse @Java
    @Execute
    public JsonResponse<ProductBean> product() {
        ProductBean bean = ...
        return asJson(bean);
    }

Form/Body Validation

You can use Hibernate Validator's annotations in form or body.

e.g. validator annotation in form @Java
public class ProductEditForm {

    @Required
    public String productName;
}

And you should call in your action.

e.g. validation as HTML response @Java
@Execute
public HtmlResponse index(OptionalThing<Integer> pageNumber
                        , ProductSearchForm form) {
    validate(form, messages -> {}, () -> {
        return asHtml(path_Product_ProductListJsp);
    });
    ...
}
e.g. validation as JSON response @Java
@Execute
public JsonResponse<SearchPagingBean<ProductRowBean>> index(
                OptionalThing<Integer> pageNumber
              , ProductSearchBody body) {
    validate(form, messages -> {});
    ...
}

Specify more validation manually at second argument.

e.g. more validation @Java
@Execute
public JsonResponse<SearchPagingBean<ProductRowBean>> index(
                OptionalThing<Integer> pageNumber
              , ProductSearchBody body) {
    validate(form, messages -> {
        if (body.productName == null) {
            messages.addConstraintsRequiredMessage("productName");
        }
    });
    ...
}

Example Code

HTML response style

e.g. Action for URL '/product/list/3' as HTML response @Java
@Execute
public HtmlResponse index(OptionalThing<Integer> pageNumber
                        , ProductSearchForm form) {
    validate(form, messages -> {}, () -> {
        return asHtml(path_Product_ProductListJsp);
    });
    PagingResultBean<Product> page = productBhv.selectPage(cb -> {
        cb.setupSelect_ProductStatus();
        cb.query().setProductName_LikeSearch(form.productName, op -> op.likeContain());
        cb.query().addOrderBy_ProductName_Asc();
        cb.paging(getPagingPageSize(), pageNumber.orElse(1));
    });
    List<ProductRowBean> beans = page.mappingList(product -> {
        return mappingToBean(product);
    });
    return asHtml(path_Product_ProductListJsp).renderWith(data -> {
        data.register("beans", beans);
        registerPagingNavi(data, page, form);
    });
}

JSON response style

e.g. Action for URL '/product/list/3' as JSON response @Java
@Execute
public JsonResponse<SearchPagingBean<ProductRowBean>> index(
                OptionalThing<Integer> pageNumber
              , ProductSearchBody body) {
    validate(body, messages -> {});
    ListResultBean<Product> page = productBhv.selectPage(cb -> {
        cb.setupSelect_ProductStatus();
        cb.query().setProductName_LikeSearch(form.productName, op -> op.likeContain());
        cb.query().addOrderBy_ProductName_Asc();
        cb.paging(getPagingPageSize(), pageNumber.orElse(1));
    });
    SearchPagingBean<ProductRowBean> bean = createPagingBean(page);
    return asJson(bean);
}

TemplatePath FreeGen (if use)

At first, make template file (e.g. JSP) (empty file for now)

File Name
related to URL form tag submits ※except buttom name
Location Directory
prefix of file name

URL requested by la:form tag when action attribute is omitted.

product/product_list.jsp
/product/list/
profile/profile_password_change.jsp
/profile/password/change/
mypage/mypage.jsp
/mypage/

Execute FreeGen task of DBFlute, and you can complement the generated path definition in your code.

e.g. Template File Location @Directory
src/main/webapp
 |-WEB-INF
    |-view // location for HTML templates
    |  |-product // related to product package
    |  |  |-product_list.jsp     // /product/list/
    |  |  |-product_purchase.jsp // /product/purchase/
    |  |
    |  |-profile
    |  |  |-profile_password_change.jsp // /profile/password/change/
    |  |  |-profile_withdrawal.jsp      // /profile/withdrawal/
    |  |
    |  |-mypage
    |  |  |-mypage.jsp // /mypage/
    |  |
    |  |-root.jsp // '/'
    |
    |-web.xml
e.g. you can use Template Path for HtmlResponse @Java
    @Execute
    public HtmlResponse index() {
        ...
        return asHtml(path_Mypage_MypageJsp); // is static definition
    }