Freemarker test if null




















You can do it like this: myMap? However, for? Note that as Java's Map is particular about the exact class of the key, at least for numerical keys calculated inside the templates you will have to cast them to the proper Java type, otherwise the item will not be found. This is because of FTL's deliberately simplified type system has only a single numerical type, while Java distinguishes a lot of numerical types.

Note that the casting is not needed when the key value comes directly from the data-model i. Certainly you are using pure BeansWrapper as your object wrapper instead of the default, DefaultObjectWrapper , or a custom subclass of it, and the simpleMapWrapper property of that is left to false.

Unfortunately, that's the default of BeansWrapper for backward compatibility , so you have to explicitly set it to true where you instantiate it. Also, at least since 2. In this case use the sequence concatenation and hash concatenation operators. Also, you may use the subsequence operator instead of removing sequence items.

It's for displaying already calculated things, not for calculating data. Keep templates simple. But don't give it up, you will see some advices and tricks bellow. Maybe if you rethink your data-model, you will realize this is possible. It seldom happens, so think twice whether that calculation or parts of it rather belongs to the data-model domain than to the presentation domain.

Let's assume you are sure it belongs to the presentation domain. For example, you want to display a keyword index on some very smart way, whose algorithm need you to create and write some sequence variables. Then you should do something like this ugly situations has ugly solutions That is, you move out the complex part of the presentation task from the template into Java code.

Note that it doesn't affect the data-model, so the presentation is still kept separated from other the other application logic. Of course the drawback is that for this the template author will need the help of a Java programmer, but for complex algorithms that's probably needed anyway. You can access the Java API of a java. Map with the help of the api built-in, like myMap? Just certain types, because TemplateSequenceModel and TemplateHashModel doesn't have methods for modification, so you will need the sequence or hash to implement some additional methods.

An example of this solution can be seen in FMPP. It allows you to do things like this pp stores the services provided by FMPP for templates :. The pp. So for example the template author can't modify a sequence that comes from the data-model with this. But beware, these solutions have a problem: The sequence concatenation , sequence slice operator like seq[ The same problem exists with the result of hash concatenation ; it just wraps the two hashes, so the resulting hash will magically change if you modify the hashes you have added earlier.

As a work-around, after you did the above problematic operations, either be sure you will not modify the objects that were used as input, or create a copy of the result with a method provided by the solution described in above two points e.

Of course this is easy to miss The FreeMarker template language doesn't know the Java language null at all. It doesn't have null keyword, and it can't test if something is null or not. When it technically faces with a null , it treats it exactly as a missing variable. You may interested in the rationale behind this. From the viewpoint of the presentation layer a null and non-existent thing is almost always the same. The difference between this two is usually just a technical detail, which is rather the result of implementation details than of the application logic.

And how could FreeMarker tell if something concrete equals with something that is missing and thus unknown? Or if two missing unknown things are equal? Of course these questions can't be answered. There is at least one problem with this null -unaware approach. When you call a Java method from a template, you may want to pass a null value as argument since the method was designed to be used in Java language, where the concept of null is known. In this case you can exploit a bug of FreeMarker that we will not fix until we provide a correct solution for passing null values to a method : if you specify a missing variable as the argument, then it will not cause an error, but a null will be passed to the method instead.

Like foo. Capture the output into a variable with the assign or local directive. This is because the character that you want to print can't be represented with the charset encoding used for the output stream, so the Java platform not FreeMarker substitutes the problematic character with question mark. In general you should use the same charset for the output as for the template use the getEncoding method of the template object , or which is even safer, you should always use UTF-8 charset for the output.

The charset used for the output stream is not decided by FreeMarker, but by you, when you create the Writer that you pass to the process method of the template. Note that the question marks or other substitution characters may be produced outside FreeMarker, in which case the above obviously will not help.

HTML forms are another potential source of encoding problems. It's a good idea to print the numerical code of the characters of the string on various places, to see where the problem occurs first. First of all, be sure your application is designed well: templates should display data, and almost never calculate data.

If you are still sure you want to do it, read on The problem is that this runtime environment will be discarded when Template. To prevent this, you can do the below, which is equivalent with the above, except that you have chance to return the variables created in the template:. If you really can't avoid doing that you should, as it's confusing , you can solve that with constructing the appropriate FTL source code dynamically in a string, then using the interpret built-in. For example, if you want to assign to the variable whose name is stored in the varName variable:.

In general you shouldn't allow that, unless those users are application developers, system administrators, or other highly trusted personnel. If you still want to allow untrusted users to upload templates, here's what to consider:. Data-model and wrapping Configuration. By default, for objects that aren't instances of the bunch of specially handled types String , Number , Boolean , Date , Map , List , array, and a few others , their public Java API will be exposed, including most methods inherited from standard Java classes getClass , etc.

To avoid that, you have to construct the data-model so that it only exposes the members that are really necessary for the template. One possibility is using SimpleObjectWrapper via Configuration. But for many applications that's too restrictive, and instead you have to create a WhitelistMemberAccessPolicy , and create a DefaultObjectWrapper or other BeansWrapper subclass that you would use that uses that.

Or, you can roll your own MemberAccessPolicy implementation, or even your own restrictive ObjectWrapper implementation of course.

Always expect that templates may get some objects that you haven't put into the data-model yourself. Notably, templates can always get a Locale object with the. Or the web application framework you are using may exposes some objects, like attributes from the Servlet scopes. Such objects will be still wrapped with the ObjectWrapper that you set in the Configuration , and this is why it's important to ensure safety on that level.

Controlling what objects the template will have access to is hard, but you can control centrally what members of any object they have access to.

If you are creating TemplateModel -s in custom code instead of the ObjectWrapper creating those , be sure that you avoid deprecated container constructors like new SimpleSequence , as those will use the also deprecated default object wrapper instance, which doesn't have the same restrictions than the ObjectWrapper you have set on the Configuration. Also, don't forget about the? But note that the ObjectWrapper is still in control, as it decides what objects support?

Members not allowed by the MemberAccessPolicy also won't be visible with? If you are using the default object wrapper class freemarker.

The problem with the XML wrapping feature, which wraps org. Node objects on special way to make them easier to work with in templates, is that this facility by design lets template authors evaluate arbitrary XPath expressions, and XPath can do too much in certain setups. If you really need the XML wrapping facility, review carefully what XPath expressions are possible in your setup. Also, be sure you don't use the long deprecated, and more dangerous freemarker. Also, note that when using the XML wrapping feature, not allowing org.

Node methods in the MemberAccessPolicy has no effect, since it doesn't expose Java Node members to templates directly. Last not least, some maybe aware of the historical legacy that standard object wrappers filter out some well known "unsafe" methods, like System. Do not ever rely on that, since it only blocks the methods from a small predefined list. Clearly it's impossible to blacklist all the problematic members in those. Template-loader Configuration. To avoid loading sensitive data, you have to use a TemplateLoader that double-checks that the file to load is something that should be exposed.

Source: FreeMarker Manual. This example demonstrates how to handle null values for two lists in a Freemaker template. Freemarker webite. Other reference:. Stack Overflow for Teams — Collaborate and share knowledge with a private group. Create a free Team What is Teams? Collectives on Stack Overflow. Learn more. Handling null values in Freemarker Ask Question. Asked 9 years ago. Active 7 months ago.

Viewed k times. Improve this question. Nathan 6, 6 6 gold badges 44 44 silver badges 66 66 bronze badges. Anand B Anand B 2, 9 9 gold badges 31 31 silver badges 53 53 bronze badges. Possible Duplicate: stackoverflow. Add a comment. Active Oldest Votes. Improve this answer. For example Be careful when processing like listing such ranges, as processing all items of it it would take forever or until the application runs out of memory and crashes. Just like with length limited ranges, when these kind of ranges are used for slicing, the slice will end when the end of the sliced sequence or string is reached.

Right-unbounded ranges before FreeMarker 2. To activate the new behavior, it's not enough to use FreeMarker 2. The last would create a sequence that contains an item that's a range. The square brackets are part of the slicing syntax, like seq [ myRange ]. You can write arithmetical expression on the sides of the..

Like n.. However, when listing them, their actual size is infinite. Ranges don't really store the numbers they consist of, thus for example Note that both the names and the values are expressions. The keys must be strings. The values can be if any type.

To access a top-level variable, you simply use the variable name. For example, the expression user will evaluate to the value of variable stored with name "user" in the root. So this will print what you store there:. If there is no such top-level variable, then an error will result when FreeMarker tries to evaluate the expression, and it aborts template processing unless programmers has configured FreeMarker differently.

Since FreeMarker 2. Note that these escapes only work in identifiers, not in string literals. Furthermore, since FreeMarker 2. If we already have a hash as a result of an expression, then we can get its subvariable with a dot and the name of the subvariable. Assume that we have this data-model:. Now we can read the title with book. Applying this logic further, we can read the name of the author with this expression: book.

There is an alternative syntax if we want to specify the subvariable name with an expression: book["title"]. In the square brackets you can give any expression as long as it evaluates to a string.

So with this data-model you can also read the title with book[test]. More examples; these are all equivalent: book. There are no such restrictions when you use the square bracket syntax, since the name is the result of an arbitrary expression. As with the top-level variables, trying to access a non-existent subvariable causes an error and aborts the processing of the template unless programmers has configured FreeMarker differently.

This is the same as for hashes, but you can use the square bracket syntax only, and the expression in the brackets must evaluate to a number, not a string. For example to get the name of the first animal of the example data-model remember that the number of the first item is 0, not 1 : animals[0].

Special variables are variables defined by the FreeMarker engine itself. To access them, you use the. Normally you don't need to use special variables.

They are for expert users. The complete list of special variables can be found in the reference. Interpolations work only in text sections e. This mostly leads to problems with numbers, as many locales use grouping thousands separators by default, and so "someUrl? To prevent this, use the? You can get a single character of a string at a given index similarly as you can read the subvariable of a sequence , e.

The result will be a string whose length is 1; FTL doesn't have a separate character type. As with sequence sub variables, the index must be a number that is at least 0 and less than the length of the string, or else an error will abort the template processing.

Since the sequence subvariable syntax and the character getter syntax clashes, you can use the character getter syntax only if the variable is not a sequence as well which is possible because FTL supports multi-typed values , since in that case the sequence behavior prevails. To work this around, you can use the string built-in , e. Don't worry if you don't understand this yet; built-ins will be discussed later.

You can slice a string in the same way as you slice a sequence see there , only here instead of sequence items you work with characters.

Some differences are:. Decreasing ranges aren't allowed for string slicing. That's because unlike sequences, you seldom if ever want to show a string reversed, so if that happens, that's almost always the result of an oversight.

If a value is both a string and a sequence a multi-typed value , then slicing will slice the sequence instead of the string. When you are processing XML, such values are common. In such cases you can use someXMLnode? There's a legacy bug where a range with inclusive end that's one less than the starting index and is non-negative like in "abc"[ It should be an error as it's a decreasing range.

Currently this bug is emulated for backward compatibility, but you shouldn't utilize it, as in the future it will be certainly an error. Note that sequence concatenation is not to be used for many repeated concatenations, like for appending items to a sequence inside a loop. Although concatenating sequences is fast and is constant time it's speed is independently of the size of the concatenated sequences , the resulting sequence will be always a little bit slower to read than the original two sequences were.

Thus, after tens or hundreds of repeated concatenations the result can be impractically slow to reader. With seq [ range ] , were range is a range value as described here , you can take a slice of the sequence.

The resulting sequence will contain the items from the original sequence seq whose indexes are in the range. Furthermore, the items in the slice will be in the same order as in the range. Thus for example the above example with the The numbers in the range must be valid indexes in the sequence, or else the processing of the template will be aborted with error.

Like in the last example, seq[ Note that seq[ Length limited ranges start.. They will slice out at most as many items as there is available:. Note above that slicing with length limited and right unbounded ranges allow the starting index to be past the last item by one but no more. To split a sequence to slices of a given size, you should use the chunk built-in. Note that hash concatenation is not to be used for many repeated concatenations, like for adding items to a hash inside a loop.

While adding together hashes is fast and is constant time independent of the size of the hashes added , the resulting hash is a bit slower to read than the hashes added together.



0コメント

  • 1000 / 1000