In this section you will learn how to interact with the Context Stack in Handlebars.java.
The Context class represent the context stack in Handlebars.java.
You rarely need to instantiate aContext
object, bc Handlebars.java does it for you
every time you call:
String output = template.apply(model);
// or
template.apply(model, writer);
Theapply
method accepts aContext
or anObject
. Theapply(Object)
function, automatically convert the object into aContext
.
while (context != null && context.get("value") == null) {
context = context.parent;
}
A value will be resolved in the current context.
If the value isn't here, the parent context need to resolved the value.
If the value isn't in the whole stack, the value is resolved to null and nothing will be rendered.
A common use case in web applications is to access to the logged user from a web page.
User user = ...;
Object model = ...;
Map modelWithUser = new HashMap();
modelWithUser.put("user", user);
modelWithUser.put("model", model);
template.apply(modelWithUser);
This isn't so bad but there are at least two drawbacks:
combine
method:
User user = ...;
Object model = ...;
Context context = Context
.newBuilder(model)
.combine("user", user)
.build();
template.apply(context);
We definitely fix the second drawback described before.
The first one depends on your application architecture. For example,
if you have ahook
method where you can globally merge the model with a view
(and of course you can access to the current logged user).
AValueResolver
is responsible of extracting a single value from a source object.
By default, only maps
andJavaBean
objects are supported.
Let you access to JavaBean properties. It is registered by default.
Context context = Context
.newBuilder(model)
.resolver(JavaBeanValueResolver.INSTANCE)
.build();
template.apply(context);
Let you access tomap
values. It is registered by default.
Context context = Context
.newBuilder(model)
.resolver(MapValueResolver.INSTANCE)
.build();
template.apply(context);
Let you access to instance fields (private or public).
Context context = Context
.newBuilder(model)
.resolver(FieldValueResolver.INSTANCE)
.build();
template.apply(context);
Let you access to public methods.
Context context = Context
.newBuilder(model)
.resolver(MethodValueResolver.INSTANCE)
.build();
template.apply(context);
You can combine any number of value resolvers according to your application data.
Context context = Context
.newBuilder(model)
.resolver(
MapValueResolver.INSTANCE,
JavaBeanValueResolver.INSTANCE
)
.build();
template.apply(context);
Context context = Context
.newBuilder(model)
.resolver(
MapValueResolver.INSTANCE,
JavaBeanValueResolver.INSTANCE,
MethodValueResolver.INSTANCE
)
.build();
template.apply(context);
Context context = Context
.newBuilder(model)
.resolver(
MapValueResolver.INSTANCE,
JavaBeanValueResolver.INSTANCE,
FieldValueResolver.INSTANCE
)
.build();
template.apply(context);
TheContext
class does all the hard work: walk through the stack, resolve expressions, etc. This component isn't puggable and can't be set.
Where aValueResolver
extracts a single value from a source. You can add, remove or even create your own value resolver
.
It plays an important role if your application deal with a custom data source.
For example,
if your service layer returns the widely usedJsonNode
from
Jackson a custom ValueResolver can access
to that object and extract values from it.
Thank you, for reading the Handlebars.java blog.