4. View first URL mapping and variable injection

4.1 View first

In Asta4D, we follow the principle of view first rather than the tradition MVC architecture. The declaration of URL rules does not need to include a controller and one url can be mapped to one template file directly, which is called as View First.

In Asta4D, URL mapping rules are not managed in a configuration file. The Framework provides a sort of DSL by a set of convinient APIs, which means the declaration of Asta4D's URL mapping rule is programmable and it affords much flexibility than the way with a static configuration file.

Users declare their own URL rules via implementing the interface UrlMappingRuleInitializer of Asta4D:

Example 4.1. Sample of declaring url rules:


public class UrlRules implements UrlMappingRuleInitializer {    
    
    @Override    
    public void initUrlMappingRules(UrlMappingRuleHelper rules) {    
        //@formatter:off    
        rules.add(GET, "/")    
             .redirect("/app/index");    
            
        rules.add(GET, "/redirect-to-index")    
             .redirect("p:/app/index");    
            
        rules.add("/app/", "/templates/index.html");    
        rules.add("/app/index", "/templates/index.html");    
        rules.add("/app/{name}/{age}", "/templates/variableinjection.html");    
        ...    
    
        //@formatter:on    
    }
}

    

4.2 The grammer of URL rule and path variable

The grammer of Asta4D's URL rule is almost the same as Spring MVC's URL mapping rule and the parts surrounded by braces are treated as path variables which can be retrieved in following process(in snippet classes or request handlers).

Further, extra path variables can be declared in a url rule by calling the method of "var" as following:

Example 4.2. Sample of declaring extra path variable:


rules.add("/app/{name}/{age}", "/templates/variableinjection.html")  
     .var("extraVar", 1234);  

    

4.3 Variable Injection

Asta4D implements a variable injection mechanism which is very closed to Spring MVC, all of the instance fields and method parameters in the implementation of snippet classes can be injected automatically by framework.

Further, all the snippet classes are singleton in request scope.In other words, there will be only one istance of any snippet class in a single request scope regardless of how many times the snippet class is called. Let us see some samples of variable injection in the snippet class.

Example 4.3. 


public class InitSnippet implements InitializableSnippet {    
    
    @ContextData    
    private String value; // (1)    
    private long id;    
    private String resolvedValue;    
    private int count = 0;    

}    

    

@ContextData indicates that the instance field "value" need to be injected after the instance of InitSnippet is created. Since the snippet instance is singeleton in the current request scope, the instance field "value" will be injected and initialized only once in the current request scope. The framework will search a variable named "value" in all the available variable scopes and inject the found value. The name of "value" is decided by the field name by default and can be sepcified by extra declaration(see the following samples).


Example 4.4. 


public class InitSnippet implements InitializableSnippet {    

    @ContextData    
    private void setId(long id) { //(3)    
        this.id = id;    
    }    

}    

    

Instance field can be injected via setter methods too.


Example 4.5. 


public class InitSnippet implements InitializableSnippet {    
    
    @Override    
    public void init() throws SnippetInvokeException { //(2)    
        resolvedValue = value + "-resolved";    
        count++;    
    }  

}    

    

The init method of InitializableSnippet is being implemented. This is not necessary but if a snippet class implements the interface of InitializableSnippet, the init method will be called once after all the instance fields are injected, by which customized snippet initial logic can be performed.


Example 4.6. 


public class InitSnippet implements InitializableSnippet {    

    // (4)    
    public Renderer getPathVarName(    
    @ContextData(scope = WebApplicationContext.SCOPE_PATHVAR)    
    int count) {    
    }

}    

    

Variable injection on snippet method. In this sample the extra search scope are delcared, which cause framework searches a variable named "count" in the path variable scope. As the same as the injection on instance field, the searching variable name is decided by the parameter name by default.


Example 4.7. 


public class InitSnippet implements InitializableSnippet {    

    // (5)    
    public Renderer getQueryParamName(    
    @ContextData(name = "var", scope = WebApplicationContext.SCOPE_QUERYPARAM)    
    String name) {    
    }    

}    

    

In this sample, an extra variable name and search scope are declared, the framework will search a variable named "var" in the request parameters.


Example 4.8. 


public class InitSnippet implements InitializableSnippet {    

    // (6)    
    public Renderer getDefaultName(String name) {    
    } 

}    

    

There is a difference between instance field injection and method parameter injection. A instance field without @ContextData annotation will not be injected, but for method paramters, all the paramters will be injected compulsorily. In this sample, the framework will search a variable named "name" in all the available scopes as following order:

  1. HTML tag attribution(SCOPE_ATTR)

    Trace back to the top tag of the current HTML document recursively. This scope is only available to the snippet method.

  2. path variable(SCOPE_PATHVAR)

  3. request parameter(SCOPE_QUERYPARAM)

  4. flash variable(SCOPE_FLASH)

    The variables passed from one request to another request, usually acrross a redirect.

  5. cookie(SCOPE_COOKIE)

  6. request hearder(SCOPE_HEADER)

  7. request attribute(SCOPE_REQUEST)

  8. session(SCOPE_SESSION)

  9. global(SCOPE_GLOBAL)

    A global static variable pool

This search order is applied to the instance field injection too except that the first scope of HTML tag attribution is not available.