public class DefaultObjectWrapper extends BeansWrapper
ObjectWrapperinterface. Usually, you don't need to create instances of this, as an instance of this is already the default value of the
object_wrapper setting. Then the
DefaultObjectWrapperwill be the same that you have set for the
Configurationitself. As of this writing, it's highly recommended to use
incompatibleImprovements2.3.22 (or higher).
If you still need to create an instance, that should be done with an
Configuration.setSetting(String, String) with
"object_wrapper" key), not with
its constructor, as that allows FreeMarker to reuse singletons. For new projects, it's recommended to set
incompatibleImprovements to 2.3.22 won't do these, as they could break legacy templates too easily.
This class is only thread-safe after you have finished calling its setter methods, and then safely published it (see
JSR 133 and related literature). When used as part of
Configuration, of course it's enough if that was safely
published and then left unmodified.
EXPOSE_ALL, EXPOSE_NOTHING, EXPOSE_PROPERTIES_ONLY, EXPOSE_SAFE
|Modifier||Constructor and Description|
|Modifier and Type||Method and Description|
Converts an array to a java.util.List.
Getter pair of
Getter pair of
The getter pair of
Called for an object that isn't considered to be of a "basic" Java type, like for an application specific type, or for a W3C DOM node.
Returns the lowest version number that is equivalent with the parameter version.
Specifies whether non-
Sets if to wrap container objects (
Wraps the parameter object to
checkModifiable, clearClassIntrospecitonCache, clearClassIntrospectionCache, coerceBigDecimal, coerceBigDecimals, coerceBigDecimals, finalizeConstruction, finetuneMethodAppearance, getDefaultDateType, getDefaultInstance, getEnumModels, getExposureLevel, getIncompatibleImprovements, getInstance, getMethodAppearanceFineTuner, getModelFactory, getOuterIdentity, getPreferIndexedReadMethod, getStaticModels, getTreatDefaultMethodsAsBeanMembers, getUseCache, isClassIntrospectionCacheRestricted, isExposeFields, isSimpleMapWrapper, isStrict, isWriteProtected, newInstance, removeFromClassIntrospectionCache, setDefaultDateType, setExposeFields, setExposureLevel, setMethodAppearanceFineTuner, setMethodsShadowItems, setNullModel, setOuterIdentity, setPreferIndexedReadMethod, setSimpleMapWrapper, setStrict, setTreatDefaultMethodsAsBeanMembers, setUseCache, toString, tryUnwrapTo, unwrap, unwrap, wrap, wrapAsAPI, writeProtect
@Deprecated public DefaultObjectWrapper()
DefaultObjectWrapperBuilder, or in rare cases,
public DefaultObjectWrapper(Version incompatibleImprovements)
DefaultObjectWrapperBuilderinstead if possible. Instances created with this constructor won't share the class introspection caches with other instances. See
BeansWrapper.BeansWrapper(Version)(the superclass constructor) for more details.
incompatibleImprovements- It's the same as in
BeansWrapper.BeansWrapper(Version), plus these changes:
Iterator, operations on it that only check if the collection is empty without reading an element from it, such as
?has_content, won't cause the a later iteration (or further emptiness check) to fail anymore. Earlier, in certain situations, the second operation has failed saying that the iterator "can be listed only once".
Enumeration-s are wrapped into
DefaultEnumerationAdapterinstead of into
EnumerationModel(as far as
true, which is the default). This adapter is cleaner than
EnumerationModelas it only implements the minimally required FTL type, which avoids some ambiguous situations. (Note that Java API methods aren't exposed anymore as subvariables; if you really need them, you can use
protected DefaultObjectWrapper(BeansWrapperConfiguration bwCfg, boolean writeProtected)
DefaultObjectWrapper(DefaultObjectWrapperConfiguration, boolean)instead if possible; it does the same, except that it tolerates a non-
protected DefaultObjectWrapper(DefaultObjectWrapperConfiguration dowCfg, boolean writeProtected)
BeansWrapper.BeansWrapper(BeansWrapperConfiguration, boolean)and sets up
public TemplateModel wrap(java.lang.Object obj) throws TemplateModelException
TemplateModelinterface(s). Simple types like numbers, strings, booleans and dates will be wrapped into the corresponding
Collection-s, arrays and
Iterator-s will be wrapped into the corresponding
DefaultMapAdapter), depending on
getForceLegacyNonListCollections(). After that, the wrapping is handled by
handleUnknownType(Object), so see more there.
obj- The object to wrap into a
TemplateModel. If it already implements
TemplateModel, it should just return the object as is. If it's
null, the method should return
BeansWrapper, has a legacy option for returning a null model object instead, but it's not a good idea).
TemplateModelwrapper of the object passed in. To support un-wrapping, you may consider the return value to implement
AdapterTemplateModel. The default expectation is that the
TemplateModelisn't less thread safe than the wrapped object. If the
ObjectWrapperreturns less thread safe objects, that should be clearly documented, as it restricts how it can be used, like, then it can't be used to wrap "shared variables" (
protected TemplateModel handleUnknownType(java.lang.Object obj) throws TemplateModelException
Node-s will be wrapped as
NodeModel-s (allows DOM tree traversal), Jython objects will be delegated to the
JythonWrapper, others will be wrapped using
When you override this method, you should first decide if you want to wrap the object in a custom way (and if so then do it and return with the result), and if not, then you should call the super method (assuming the default behavior is fine with you).
public TemplateModel wrapDomNode(java.lang.Object obj)
protected java.lang.Object convertArray(java.lang.Object arr)
public boolean getUseAdaptersForContainers()
public void setUseAdaptersForContainers(boolean useAdaptersForContainers)
List-s, arrays and such) the legacy copying approach or the newer adapter approach should be used.
trueis recommended, which is also the default when the
incompatible_improvementsof this instance was set to
Configuration.VERSION_2_3_22or higher. To understand the difference, check some of the classes that implement the two approaches:
See also the related Version History entry under 2.3.22 in the FreeMarker Manual, which gives a breakdown of the consequences.
Attention: For backward compatibility, currently, non-
List collections (like
only be wrapped with adapter approach (with
forceLegacyNonListCollections was set to
Currently the default is
true, but in new projects you should set it to
setForceLegacyNonListCollections(boolean) for more.
public boolean getForceLegacyNonListCollections()
setForceLegacyNonListCollections(boolean); see there.
public void setForceLegacyNonListCollections(boolean forceLegacyNonListCollections)
Set-s) must be wrapped by pre-fetching into a
SimpleSequence. The modern approach is wrapping into a
DefaultNonListCollectionAdapter. This setting only has effect when
true, as otherwise
SimpleSequencewill be used regardless of this. In new projects you should set this to
false. At least before
incompatible_improvements2.4.0 it defaults to
true, because of backward compatibility concerns: with
TemplateSequenceModeltemplates could access the items by index if they wanted to (the index values were defined by the iteration order). This was not very useful, or was even confusing, and it conflicts with the adapter approach.
public boolean getIterableSupport()
setIterableSupport(boolean); see there.
public void setIterableSupport(boolean iterableSupport)
Iterable-s (not to be confused with
Iterator-s) that don't implement any other recognized Java interfaces (most notably
Collection) will be recognized as listable objects (
TemplateCollectionModel-s), or they will be just seen as generic objects (JavaBean-s). Defaults to
falsefor backward compatibility, but in new projects you should set this to
true. Before setting this to
truein older projects, check if you have called
myIterable.iterator()directly from any templates, because the Java API is only exposed to the templates if the
Iterableis wrapped as generic object.
protected java.lang.String toPropertiesString()
BeansWrapper; called from
BeansWrapper.toString(). The expected format is like
"foo=bar, baaz=wombat". When overriding this, you should call the super method, and then insert the content before it with a following
", ", or after it with a preceding