Formatting a BigDecimal in Apache Velocity - java

In my velocity templates, I've been using the Velocity NumberTool to format number variables as a currency.
Most of these are primitive doubles and they work fine with this tool.
However, some are of type BigDecimal and they don't seem to be formatted at all. It'll just show the expression as is when rendered:
$global.numberTool.currency($someBigDecimalVariable)
Is there a convenient way to format a BigDecimal with Velocity as a currency? What are the alternatives?

Since you can put any object into a Velocity context, the easiest thing to do is to put your own DecimalFormat object in your context and call its format() method in the template.
Of course this isn't a very nice solution but you can refine it to make it more generic.

Can you use JSTL in Velocity? I used the fmt JSTL Tags for displaying BigDecimals as a Currency like this:
<fmt:formatNumber value="${myBigDecimalValue}" type="currency" currencySymbol="€" currencyCode="EUR" minFractionDigits="2" maxFractionDigits="2"/>

Related

How to remove scientific notation from double

I have a bean which has a property of type double. When I pass this bean to view layer, it shows the value in scientific notation For example: 9.78313E+10 instead of 97831300000.
I want the result without scientific notation and I cannot change the data type of that field. Please let me know if there is any workaround.
You can use the printf() with %f:
System.out.printf("%.0f", value);
Here you can find a beautiful printf format cheat sheet by Alvin Alexander that might help you (and hopefully others) a lot.
How the number is shown depends on the formatting that is used by the component showing the value. If you can't access that code to use a different formater; then there is nothing you can do.
See https://docs.oracle.com/javase/tutorial/java/data/numberformat.html for starters.
One option might be: can you exchange the bean implementation; so instead of providing a "double" number; can you change it to provide a string (in that case, you could control the formatting of the number).

How to customize number format in freemarker?

I am using freemarker and trying to display numbers in this format: $3,343,434.00 for example. This was easily taken care of by using ${total?string.currency} (assuming "total" is some number).
However, when I have negative numbers, it's showing them like this: ($343.34) instead of this: -$343.34. I need the negative sign instead of the parenthesis. Is there a way I could customize the formatting so it does everything that the string.currency did but replace the negative value behavior? I am relatively new to freemarker, so detailed responses are appreciated!
You can also try ?string(",##0.00"). However in this case you need to explicitly add $ and - sign would be after $ in case of negative numbers.
<#local total = 3343434/>
$ ${total?string(",##0.00")} //$ 3,343,434.00
<#local total = -3343434/>
$ ${total?string(",##0.00")} //$ -3,343,434.00
OR in case if you want what was expected you can replace the strings.
<#local total = -3343434/>
<#local total = "$ " + total?string(",##0.00")/>
${total?replace('$ -','- $')} //- $3,343,434.00
Update: Since FreeMarker 2.3.24 you can define named custom number formats, which can be an alias to a number format pattern (or even a formatter implemented in Java, but that level of flexibility isn't needed in this case). So add a custom number format called "money" as an alias to "¤,##0.00" to the FreeMarker configuration, and then you can write something like ${total?string.#money}. See: http://freemarker.org/docs/pgui_config_custom_formats.html
Currently FreeMarker just uses the formatting facility of the Java platform, so it's only as configurable as that (assuming you want to use ?string and ?string.somethingPredefiendHere). Which is not much... but, in general, the formatting categories provided by the Java platform is not fine-gradient enough anyway, I mean, you don't have application-domain categories like, price-of-product, a salary, a price on the stock, etc. (This demand is more frequent with non-currency numbers though.) So I think, generally, you want to make a formatter function, that you can use like ${salary(someNumber)}, ${price(someNumber)}, etc. Those functions can be implemented in a commonly #included/#imported template like a #function or in Java by using #assign salary = 'com.example.SalarayMethod'?new() in place of #function, where com.example.SalarayMethod is a TemplateMethodModelEx.
How about taking a mod of your number, convert it to the required string format and finally add a '-' prefix to the final string. You can retain the default format in just two steps.
Freemarker uses the currency formatting provided by the Java platform.
It requires a little tweaking of the DecimalFormat returned by NumberFormat.getCurrencyInstance() (which is what is called when you call .currency). You can see examples of it here.
However, that said it will likely be more effective for you to create a macro in freemarker to call which will handle your specific formatting.
Sorry for not having an example of what that macro would look like, but it's a good starter into macros in freemarker since you are just learning.
You might investigate if you can supply a custom format using the exposed configuration for number formats that will meet your needs.
If you want to maintain the default currency formatting (in case you need to use a locale other than '$'), you can just replace the parentheses like so:
${transaction.amount?string.currency?replace("(","-")?replace(")","")}
This will work without error regardless of if a number is negative or positive.
TIP: Make sure the number is actually a number with the ?number directive before converting to a currency format

JSTL format String with Mask

is anybody know how to format String with mask using jstl tags? let say you want to show confidential credit card number in list and you just want to show first 4 digit and else will be masked with * something like :
1234-****-****-****
I don't think there is anything out of the box to do this. The fmt namespaced tags are about formatting numbers and dates and i18n stuff, but nothing about string formatting. If you don't want to be doing this in your presentation layer with scriptlets or function invocations, you might want to consider adding another model property for the obfuscated CC number that way you can do the formatting in Java where it will be much easier.

BigDecimal in JSTL, divide by int or double returns integer

<fmt:formatNumber var="instAmount" value="${invoice.amount / offer.getTotalInstallments()}" minFractionDigits="2" />
Where amount is BigDecimal in Java and totalInstallments is int. I tried by setting totalInstallments to double but nothing changes. It returns an Integer, it behaves as when you divide two integers in Java, you get an integer.
Am I missing something or is there a workaround?
The easiest solution is to just do this calculation in the controller/servlet and use the result on the view page. I think calculations should be done in the controller and not the view. You would use the divide() method on the BigDecimal.
That said, if you do want to do this in the view you have to define a JSTL function in a tag library and create a static version of divide which accepts the BigDecimal and the int you are diving by.
You can do it like this:
< fmt:parseNumber value="${invoice.amount}" var="a" />
< fmt:parseNumber value="${offer.value)}"  var="b" />
${a/b}

How to format Numbers in Velocity Templates?

I am getting a java object in my velocity template. The object has a double value which I want to format to 2 decimal places and display it in my template.
The class for which im getting an object is something like this
Class Price
{
double value;
String currency;
}
In my velocity template, im getting the value like this
$price.value
but I need to format it to 2 decimal places before displaying it.
I want to convert
23.59004 to 23.59
35.7 to 35.70
3.0 to 3.00
9 to 9.00
Please tell me how can I do it in velocity template? I searched a lot for this and found that I can use velocity tools, but there are no examples related to it? and can i use velocity tools in templates?
Velocity tools are expected to be used in Velocity templates; essentially they are objects added to the variables available in a template so that you can use $numberTool.format("#0.00", $val) or similar. If none of the available tools don't fit your needs, simply create a POJO and add it to the template.
To make it working you also should add the following maven dependency:
<dependency>
<groupId>org.apache.velocity</groupId>
<artifactId>velocity-tools</artifactId>
<version>2.0</version>
</dependency>
and write following code:
context.put("numberTool", new NumberTool());
#set($String = "abc")
$String.format("%.2f", $val)
$val has to be Double or Float in this case...
formatCurrency($value). This is good java velocity code to format a number to currency format.
Use the MathTool from the VelocityTools project.
$math.roundTo(2, $val)
Solution by just using the Java Formatters: (without additional libraries)
NumberFormat decimalFormat = new DecimalFormat("#.00");
velocityContext.put("decimalFormat", decimalFormat);
Int Number: $decimalFormat.format($obj.intNum)
And here is how the timestamp is formatted to human readable date.
DateFormat DATETIME_FORMAT = new SimpleDateFormat("dd/MM/yyyy HH:mm:ss");
velocityContext.put("datetimeFormat", DATETIME_FORMAT);
Timestamp to Date: $datetimeFormat.format($obj.timestamp)
$numberTool.format("#0.00", $val)
A better way to do things besides using $numberTool.format is to use one of the MessageFormat-based tool classes that do more than just numbers. For example, we use MessageTool which is Struts-specific, but you can use something similar like ResourceTool instead:
resources.properties
some.key=The price is currently {0,number,$#.##}
template.vm
<p>
$msg.get('some.key', 'resources', [$price])
</p>
This way, you get the number in context and not just all by itself. In a non-English language, the number might be more appropriate to come to the left of the text, or in the middle, or whatever. This gives you much more flexibility than simply formatting the number all by itself.

Categories

Resources