sábado, 25 de febrero de 2012

5 opciones de hosting para aplicaciones Java

La tecnología avanza y hoy en día tenemos nuevas opciones para hospedar las aplicaciones de tal forma que estén las 24 horas de los 365 días del año (o 366) disponibles para ofrecer sus servicios. Veamos algunas de las que hemos tenido hasta el momento con algunas de sus características.

Servidor propio
Disponer de un servidor propio tiene varias ventajas como que tenemos total control sobre la máquina y en la que podremos instalar todo lo que necesitemos sin ninguna limitación, sin embargo, esta ventaja también puede ser una desventaja ya que tendremos que tener los conocimientos y tiempo para administrar la máquina. Otra desventaja es que deberemos solventar los fallos de hardware que se produzcan como una rotura de un disco duro, un sobrecalentamiento de la placa base, memoria, procesador o router lo que puede afectar a la disponibilidad de la aplicación. Además, tendremos que disponer de un sitio adecuado para alojar la máquina y de los costes que conlleva tenerla encendida en todo el momento que no hay que despreciar. También tenemos que tener en cuenta que si necesitamos escalar la aplicación tendremos más dificultades que otras opciones ya que tal vez tengamos que adquirir nuevo hardware y haya que adaptar la aplicación.

En definitiva esta opción nos obliga no solo a centrarnos en nuestra aplicación sino también en la infraestructura donde se despliega y en su administración. Sin embargo, hay que decir que una gran ventaja es que nuestros datos están bajo nuestro control y no en segundas o terceras partes.

A pesar de todas sus desventajas esta opción puede ser muy interesante para un uso personal. Como por ejemplo disponer de un servidor para descargas, compartir archivos u ofrecer servicios de red a los equipos de nuestra casa. Hay diferentes plataformas sobre las que podemos implementar nuestro propio servidor, algunas de las más conocidas en estos momentos son las placas Pandaboard, SheevaPlug, BeagleBoard, TimSlice o las inminentes Raspberry Pi (¡que cuestan 35$!). Todas ellas tienen en común que son un ordenador completo que no ocupan mucho más que un disco duro de 2.5" y están basadas en microprocesadores ARM con lo que tienen un consumo muy reducido que notaremos en la factura de la luz (consumen entre 2W y 9W, ¡un ordenador de sobremesa consume entre 150W y 300W! por lo que el coste de las placas se amortiza con el tiempo). Al ser ordenadores completos y de propósito general podremos darle otros usos como centro multimedia para reproducir películas, vídeos o fotos en la televisión ya que algunas placas tienen una salida HDMI.

Proveedores de hosting
Si no queremos administrar el hardware ni tampoco el software y nos queremos olvidar de los fallos del mismo podemos hacer uso de alguna de las opciones que ofrecen los proveedores de hosting. Sin embargo, con estas opciones no tendremos posibilidad de elegir la plataforma con la que construir nuestra aplicación ya que la mayoría solo ofrece bases de datos MySQL, la plataforma ASP o ASP.NET o PHP y tal vez no en la versión que queramos. Tradicionalmente los proveedores de hosting que ofrecían la plataforma Java han sido muy pocos con lo que los programadores de Java tendremos que buscar otras opciones. A no ser que dispongamos de un servidor dedicado nuestra aplicación competirá con las otras aplicaciones por los recursos del servidor lo que puede afectar a la capacidad de nuestra aplicación. En caso de que optemos por un servidor dedicado tendremos el problema de la escalabilidad si la aplicación lo demanda.

Algunos de los proveedores más conocidos son Arsys y Piensasolutions.

Actualmente la tendencia en diferentes ámbitos está en la computación en la nube y en esta tendencia el hospedaje de las aplicaciones se ofrecen como servicio. Hay diferentes opciones entre las que poder elegir y con diversas características que deberemos evaluar según las necesidades. Veamos algunas de las más conocidas.

Otra opción es el alojamiento web de anw que tiene la ventaja de ser una opción más económica que un servidor privador virtual dedicado o una máquina cloud, ofreciendo hosting Java con JDK y servidor de aplicaciones dedicado pero a precios de hosting compartido. Poseen un panel de administración mediante el que elegir tanto la versión del JDK como del servidor de aplicaciones entre los que están los principales como Tomcat, Glassfish/Payara o WildFly y disponer del servidor funcionando en pocos minutos y en todo momento con soporte técnico. También ofrecen alojamiento web para aquellos que utilizan WordPress.

Amazon EC2
Amazon EC2
Amazon EC2 ofrece su infraestructura como servicio (IaaS) en la que nuestra aplicación estará hospedada en sus servidores. En esta opción tendremos un gran control sobre el software que instalamos en el servidor ya que en gran medida lo que la diferencia de un servidor propio es que nos conectamos al servidor de forma remota para administrarlo, si el servidor propio lo administrásemos de forma remota ni eso.

Al igual que otras opciones de la nube tiene la ventaja de que en caso de que nuestra aplicación escale podemos adquirir mas recursos de cómputo, como capacidad de procesamiento, memoria o almacenamiento en disco. En realidad Amazon no dispone una máquina física para cada servidor de sus usuarios sino que da una representación lógica de un servidor, por esto motivo, si necesitemos disponer de una nueva máquina podremos disponer de ella en pocos minutos y la podremos aprovisionar rápidamente con imágenes de software (AMI) buscando una que se adecue a nuestras necesidades. Aunque necesitemos más tiempo de configuración que en las opciones de Google App Engine y Jelastic.

Se puede probar durante un año gratis en una instancia micro. Aquí pueden consultarse los precios de Amazon EC2 y aquí los tipos y características de las instancias. A la hora de pagar hay que preseleccionar un tipo de instancia por lo que necesitaremos evaluar nuestras necesidades por lo alto y probablemente estemos pagando por capacidad que luego no aprovechamos.

Amazon también proporciona una plataforma PaaS, AWS Elastic Beanstalk, sino queremos ser responsables de administrar a bajo nivel las máquinas. Beanstalk nos permite centrarnos en el desarrollo de la aplicación en vez de la administración de la infraestructura.

Google App Engine (GAE)
Google App Engine
La solución de Google para el «cloud computing» ofrece una plataforma como servicio (PaaS) para las aplicaciones con una serie de API que deberán usar para conseguir ciertas funcionalidades, como persistencia. Tiene como ventaja que no tenemos que preocuparnos de administrar un servidor y todas las herramientas para hacerlas funcionar entre si, solo nos preocuparmos por nuestra aplicación. Tiene como desventaja que deberemos adaptar nuestra aplicación a las API que nos ofrece GAE y por tanto estaremos encadenados a su plataforma. También estaremos limitados a utilizar Python o Java por el momento.

Dispone de cuotas parte de las cuales pueden usarse de forma gratuita y aquí los precios de los recursos consumidos.

Jelastic
Jelastic
Una opción más reciente para únicamente la platforma Java, por el momento, es Jelastic. Se trata de una PaaS sin la desventaja de tener que administrar un servidor como en Amazon y sin la desventaja de estar encadenados a ciertas API como en el caso de Google App Engine de tal modo que si queremos cambiar de proveedor no tendremos que reimplementar la aplicación. Nos ofrece herramientas estándares sobre las que de desarrollar la aplicación como son nginx como servidor web, apache tomcat 6/7, jetty o glashfish como contenedores de aplicaciones, Maria DB, MySQL o PostgreSQL como bases de datos relacionales y MongoDB o CouchDB como bases de datos no-sql y el JDK 6 o 7.

Esta opción permite centrarse en el desarrollo de la aplicación y posiblemente sea la opción más adecuada para un equipo de developers puro que no dispone de sysadmins. La aplicación se puede tener en funcionamiento en minutos (en vez de horas como en Amazon EC2) ya que todos los elementos de la infraestructura ya están configurados para funcionar entre si. Dado que no hay que aprender nuevas API como en el caso de GAE permite aprovechar los conocimientos que todo desarrollador Java ya tiene.

La escalabilidad y el coste se mide en cloudlets. Un cloudlet se corresponde con 128 MiB de memoria y 200 Mhz de cómputo y tiene un precio de 0,016 €/hora (para el proveedor dogado). Aún en estado beta puede probarse de forma gratuita. La aplicación puede escalar de forma transparente de forma vertical hasta un máximo de 16 cloudlets y en horizontal hasta un máximo de 4 máquinas.

OpenShift
OpenShift (de la mano de RedHat) es una opción similar a Jelastic, es un PaaS, pero soporta diferentes tecnologías además de Java como PHP, Ruby, Node.js y Python. También diferentes bases de datos como MySql, PostgreSql y MongoDB. Puede ser probada de forma gratuita con un límite de 3 gears, donde cada gear se corresponde con 512 MiB y 1 GiB de espacio en disco. Otra opción similar es AppFog que también tiene una capa gratuita.

Otras opciones son AppFog (esta es muy recomendable), Cloud Foundry (VMWare), Heroku, Azure (Microsoft) y Google Compute Engine (Google Cloud Platform).

Como se ve las opciones de hosting o alojamiento no son pocas cada una con varias características, precios y formas de cobro diferentes.

Después de unos años he revisado este artículo con algunas opciones más de hosting que en el momento de escribirlo no conocía. El artículo es Nueva visita a 5+ opciones de «hosting» para aplicaciones.

Referencia:
http://es.wikipedia.org/wiki/Computaci%C3%B3n_en_la_nube
http://archlinuxarm.org/
http://www.raspberrypi.org/
http://pandaboard.org/
http://www.danielclemente.com/consumo/
http://www.arsys.es/
http://www.piensasolutions.com/
http://aws.amazon.com/es/ec2/
http://code.google.com/intl/es-ES/appengine/
http://cloud.google.com/
http://jelastic.com/
https://www.appfog.com
https://openshift.redhat.com
http://www.windowsazure.com/es-es/
http://blog.jelastic.com/2012/02/09/jelastic-versus-heroku/

sábado, 18 de febrero de 2012

Debug de una aplicación Java

Java
Durante el desarrollo de una aplicación es normal que se produzcan excepciones y errores. Para descubrir sus causas y depurarlos se pueden utilizar varias herramientas. Una de ellas es utilizando un sistema de trazas como slf4j en el que podamos ver que ha estado haciendo la aplicación en el momento del fallo. Con la traza de la excepción la mayoría de las veces es suficiente para reproducir el error en una máquina de desarrollo pero en ocasiones hay «bugs» que si no se «tracean» o «debuggean» con un depurador no es fácil seguir la pista al código que se está ejecutando.

Para depurar una aplicación en Java hay que arrancar la máquina virtual en modo debug de tal forma que luego con un IDE como eclipse podamos depurar la aplicación. Los parámetros a añadir a la linea de comandos que arranca la JVM son:

-Xdebug -Xrunjdwp:transport=dt_socket,address=8000,server=y,suspend=n

Si estamos depurando una aplicación web que se ejecuta en el contenedor Tomcat los shell scripts que lo arrancan nos lo ponen más fácil, tan solo tendremos que iniciar Tomcat con el siguiente comando y él se encargará de pasar los parámetros anteriores a la JVM:

catalina.sh jpda start

Para arrancar Tomcat en modo debug desde Ant podemos utilizar la siguiente tarea:

...
<condition property="LIB_HOME" value="/home/picodotdev/java">
 <and><os family="unix"/></and>
</condition>

<property name="TOMCAT" value="apache-tomcat-7.0.25"/>

<condition property="TOMCAT_STARTUP" value="startup.sh">
 <and><os family="unix"/></and>
</condition>
<condition property="TOMCAT_CATALINA" value="catalina.sh">
 <and><os family="unix"/></and>
</condition>
<condition property="TOMCAT_SHUTDOWN" value="shutdown.sh">
 <and><os family="unix"/></and>
</condition>
...
<target name="serverStartDebug">
 <exec executable="${LIB_HOME}/${TOMCAT}/bin/${TOMCAT_CATALINA}" dir="${LIB_HOME}/${TOMCAT}/bin/">
     <arg line="jpda start"/>
 </exec>
    <waitfor maxwait="10" maxwaitunit="second">
     <socket server="localhost" port="8080"/>
 </waitfor>
</target>
...

Una vez que tenemos la máquina virtual arrancada en modo debug podremos depurar la aplicación desde un IDE. En el siguiente paso veremos como hacerlo desde eclipse. Para ello en el eclipse iremos al menú «Debug > Debug Configurations > Remote Java Application» e indicaremos los parámetros: proyecto que queremos depurar, tipo de conexión (Standard (Socket Attach)), Host (localhost, si la JVM donde está ejecutandose la aplicación es la máquina local) y puerto (8000, lo mismo indicado que en el parámetro address).


Dado que en realidad nos estamos conectando a la máquina virtual de Java de forma remota y a través de la red tal vez necesitemos abrir el puerto 8000. Si tenemos un sistema Linux y ufw como firewall lo podremos hacer con:

$ sudo ufw allow 8000
$ sudo ufw status


 Una vez hayamos realizado los pasos anteriores estamos listos para «debuggear», podremos añadir puntos de ruptura donde queramos en la aplicación y podremos ver las variables y sus valores presentes en el ámbito de donde se ha parado la aplicación.


Referencia:
http://wiki.apache.org/tomcat/FAQ/Developing#Q2

viernes, 10 de febrero de 2012

Por qué usar enums en vez de constantes en Java

Java
En las versiones anteriores a la versión 1.5 o 5 de Java no existían los tipos de datos enum con lo que debíamos usar constantes de la siguiente forma:

public static String COLOR_ROJO = "rojo";
public static String COLOR_VERDE = "verde";
public static String COLOR_AZUL = "azul";

A partir de la versión 5 de Java se incorporarón al lenguaje los tipos de datos enumerados con el objetivo de mejorar varios aspectos sobre el uso de las constantes. Básicamente, un enum en Java es un conjunto fijo y relacionado de constantes como pueden ser los días de la semana y deberían usarse siempre que se necesite representar un conjunto de constantes con esas características. La característica de relacionado es importante, las constantes solo lo están por la convención que sigamos al darles un nombre. Los enums se definen de la siguiente forma:

public enum Dia {
 LUNES, MARTES, MIERCOLES, JUEVES, VIERNES, SABADO, DOMINGO
}

public enum Color {
        ROJO("FF0000"), 
 VERDE("00FF00"), 
 AZUL("0000FF");

 private final String rgb;

 Color(String rgb) {
  this.rgb = rgb;
 }

 public String getRGB() {
  return rgb;
 }
}

Como son constantes por las convenciones del lenguaje se escriben en mayúscula. Pero los enum son algo más que constantes, la clase del tipo del enum puede definir métodos y otras propiedades, como el método getRGB del ejemplo anterior o en el siguiente caso que se usa el método values() y que se añade automáticamente a todos los enums.

for (Dia d : Dia.values()) {
    System.out.printf("El día de la semana %s", d);
}

for (Color c : Color.values()) {
    System.out.printf("El color %s tiene como RGB %s", c, c.getRGB());
}

Algunas cosas que hacen de los enum muy interesantes es que al definir las constantes de este modo obtenemos «type safety». Si decimos que un método de una clase recibe un enum el compilador comprobará en tiempo de compilación que cuando lo usamos le pasemos realmente un valor de ese enum, cosa que con constantes definidas como int o String el compilador solo comprueba que pasemos un int o String y por tanto podremos pasar cualquier valor aunque no sea una de las constantes esperadas por el método. Otra de las ventajas que ya se ve en ejemplo anterior es que los enums pueden tener comportamiento a través de los métodos que defina. También, específicamente diseñadas para los enums existen las clases EnumSet y EnumMap que trabajan con enums de forma más eficiente que con Set y Map. Además, los enums pueden ser usados en expresiones switch cosa que con constantes de tipo String solo podemos hacer a partir de la versión 7 de Java..

Para comprarar valores de enums podemos hacerlo con el operador == o con el método equals. Usar el operador == tiene la ventaja de evitar un posible NullPointerException y de que el compilador comprueba que se estén comparando dos valores del mismo enum.

== nunca lanza NullPointerException

Dia dia = null;
if (dia == Dia.LUNES);      // se ejecuta
if (dia.equals(Dia.LUNES)); // lanza NullPointerException

== comprueba compatibilidad de tipos en tiempo de compilación

if (Dia.LUNES.equals(COLOR.ROJO)); // compila bien
if (DIA.LUNES == COLOR.ROJO);      // no compila, incompatibilidad de tipos

Estos son motivos suficientes para usar enums en vez de constantes y == en vez de equals para los enums a partir de la versión 5 de Java. Las constantes son mejor que tener en nuestro código «hardcodeados» los valores y con ellas obtendremos la asistencia de IDEs como eclipse para saber donde se utilizan y podremos hacer un refactor si necesitamos hacer un cambio de nombres («refactorización»). Pero los enums superan en ventajas a las constantes por los motivos anteriores asi que si podemos utilizar en nuestros proyectos Java 5 o superior es aconsejable utilizarlos.

Referencia:
http://docs.oracle.com/javase/tutorial/java/javaOO/enum.html
http://stackoverflow.com/questions/1750435/comparing-java-enum-members-or-equals
http://www.javabeat.net/tips/171-how-to-use-enum-in-switch.html

sábado, 4 de febrero de 2012

Recarga de clases (class reloading) en Apache Tapestry

Apache Tapestry
En el mundo Java de desarrollo de aplicaciones web hace no tanto tiempo un cambio en una clase implicaba reiniciar el servidor para ver los cambios. Dado que desarrollando una aplicación los cambios son pequeños, incrementales y numerosos esto implicaba tener que reiniciar constantemente el servidor que dependiendo de la aplicación esto podría llevar no mucho tiempo, desde 10-30, que ya es un tiempo considerable, pero podría llegar a llevar incluso algunos minutos. El tiempo de espera para cada reinicio normalmente es tiempo no productivo que acumulándolo a lo largo del día puede llegar a ser considerable y por ello los frameworks web están evolucionando a no tener que requerir reiniciar el servidor para detectar las modificaciones, esto es, cogiendo los cambios en caliente. Ello nos permite ser más productivos.

Apache Tapestry evlucionó y no se quedó atras. La recarga de clases o «class reloading» es una característica añadida en Tapestry en la versión 5 para las clases de las páginas y componentes al igual que los archivos .tml de las plantillas y los los archivos de catálogos de mensajes. En la versión 5.2 la recarga de clases se extendió a los servicios definidos en los módulos de Tapestry. El proceso de recarga que hace Tapestry cuando se detecta un cambio en una clase no afecta a los datos persistentes ya que estos se guardan aparte, normalmente en la sesión, con lo que el desarrollo nos será muy cómodo.

Si nuestra aplicación tiene como paquete base com.blogspot.elblogdepicodev.tapestry Tapestry recargará las clases de los siguientes paquetes cuando detecte algún cambio:
  • com.blogspot.elblogdepicodev.tapestry.pages
  • com.blogspot.elblogdepicodev.tapestry.components
  • com.blogspot.elblogdepicodev.tapestry.mixins
  • com.blogspot.elblogdepicodev.tapestry.base
Sim embargo, el proceso tiene algunas limitaciones. La recarga solo se aplica a clases y archivos que están en el sistema de archivos y no obtenidos desde archivos JAR. Aunque esta limitación no es importante en desarrollo ya que podemos desplegar la aplicación en nuestro servidor de desarrollo de forma expandida.

El coger los cambios en caliente es una característica deseable de todo framework actual pero también hay que tener en cuenta el tiempo de inicio del servidor ya que en algún momento tarde o temprano nos tocará hacerlo, si queremos ser ágiles en el desarrollo no es recomendable esperar varios minutos a que el servidor termine de iniciarse y en producción es necesario que el tiempo de interrupción sea mínimo.

Un Tomcat sin ninguna aplicación tarda en iniciarse unos 4 segundos, con una aplicación Tapestry desplegada de forma expandida con Hibernate, EhCache y Quartz de tamaño medio tarda unos 10 segundos y en servir la primera página unos 15-20 segundos.

Referencia:
Documentación sobre Apache Tapestry

viernes, 27 de enero de 2012

last, como obtener los últimos inicios de sesión

Linux
El comando last es una pequeña utilidad que nos permite conocer cuando se inició la sesión y cuando finalizó, con que usuario y desde que dirección IP se realizaron los últimos inicios de sesión a un sistema. Quizá esta información no sea de utilidad en alguna situación o para detectar intrusiones a un sistema. Su uso es muy simple:

$ last -F -10

Este comando nos permite conocer los ultimos 10 inicios de sesión en el sistema. Si queremos conocer los inicio de sesión realizados por un determinado usuario lo haríamos con:

$ last -F -10 root

Este comando tiene unos cuantos parámetros más que pueden consultarse en la página man del comando.

last

sábado, 21 de enero de 2012

Errores de precisión, redondeo y representación con float y double

Java
Los tipos de datos float y double aunque muy usados y útiles tienen defectos, como que no son capaces de representar el resultado de ciertas operaciones ariméticas entre números reales con total precisión, en algunos casos solo son capaces de representar aproximaciones a ellos y que las operaciones las realizan en base dos. Al igual que nosotros no podemos repsentar 1/3 con números en base diez con total exactitud (solo una aproximación 0,333333333... con treses hasta el infinito) a las computadoras les pasa otro tanto de lo mismo, aunque estas guardan los números en base dos. Por tanto usarlos para hacer ciertas operaciones aritméticas, y siendo acumuladas varias de ellas, puede dar lugar a errores de redondeo y precisión en el resultado final. Por estos motivos usar estos tipos de datos no son los más adecuados para trabajar en una aplicación que calcule precios. Veámoslo con un ejemplo.

Supongamos que tenemos una cantidad de dinero tal que 100,05 a la que aplicamos un 10% de descuento y posteriormente un 5% en concepto de impuestos. Las líneas de código que calculan esto son:

import java.text.NumberFormat;

double amount = 100.05;
double discount = amount * 0.10;
double total = amount - discount;
double tax = total * 0.05;
double taxedTotal = tax + total;

NumberFormat money = NumberFormat.getCurrencyInstance();
System.out.println("Subtotal: "+ money.format(amount));
System.out.println("Discount: " + money.format(discount));
System.out.println("Total: " + money.format(total));
System.out.println("Tax: " + money.format(tax));
System.out.println("Tax+Total: " + money.format(taxedTotal));

Y el resultado es:

Subtotal: 100,05 €
Discount: 10,00 €
Total: 90,04 €
Tax: 4,50 €
Tax+Total: 94,55 €

Si nos fijamos en la suma de total más impuestos hay una diferencia de 0.01 y si presentamos un desglose de precios como este a un usuario puede que este piense que hay algún error en el cálculo, le genere desconfianza y no haga la compra en el peor de los casos. Viendo los valores sin los redondeos que hace NumberFormat tenemos:

Subtotal: 100.05
Discount: 10.005
Total: 90.045
Tax: 4.50225
Tax+Total: 94.54725

Los redondeos que hace NumberFormat es HALF_EVEN por defecto, de modo que cuando un decimal está equidistante a las dos partes se redondea a la parte par por lo que con una precisión de dos decimales:

Discount: 10.005 se redondea a 10.00
Total: 90.045 se redondea a 90.04
Tax: 4.50225  se redondea a 4.50
Tax+Total: 94.54725 se redondea a 94.55

En este caso se trata de un problema de redondeo pero ahora supongamos que tenemos una cantidad de 0,70 céntimos a la que no aplicamos un descuento pero si el procentaje de impuestos del 5%. Tendríamos:

import java.text.NumberFormat;
double amount = 0.70;
double tax = amount * 0.05;
double taxedTotal = tax + amount;

NumberFormat money = NumberFormat.getCurrencyInstance();
System.out.println("Subtotal: "+ money.format(amount));
System.out.println("Tax: " + money.format(tax));
System.out.println("Tax+Total: " + money.format(taxedTotal));

Subtotal: 0,70 €
Tax: 0,03 €
Tax+Total: 0,74 €

Nos encontramos otra vez con la diferencia de 0.01. Vemos los valores sin redondear por NumberFormat:

Subtotal: 0.7
Tax: 0.034999999999999996
Tax+Total: 0.735

Aquí se ve que el resultado de ciertas operaciones aritméticas entre datos double (o float) son almacenadas por una computadora con errores de precisión, 0.70 * 0.05 (debería ser 0.035).

Para evitar estos errores debemos utilizar la clase BigDecimal que pemite almacenar números con una precisión en la práctica infinita en base 10, realizar los cálculos como los humanos esperan, en base diez, y hacer los redondeos de precisión. Aplicando una precisión de dos decimales a los números y usando BigDecimal tenemos:

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.NumberFormat;

RoundingMode RM = RoundingMode.HALF_EVEN;
BigDecimal amount = new BigDecimal("100.05"); 
BigDecimal discountPercent = new BigDecimal("0.10");
BigDecimal discount = amount.multiply(discountPercent).setScale(2, RM); 
BigDecimal total = amount.subtract(discount).setScale(2, RM);
BigDecimal taxPercent = new BigDecimal("0.05");
BigDecimal tax = total.multiply(taxPercent).setScale(2, RM);
BigDecimal taxedTotal = total.add(tax).setScale(2, RM);
NumberFormat money = NumberFormat.getCurrencyInstance(); 
System.out.println("Subtotal : " + money.format(amount));
System.out.println("Discount : " + money.format(discount));
System.out.println("Total : " + money.format(total)); 
System.out.println("Tax : " + money.format(tax)); 
System.out.println("Tax+Total: " + money.format(taxedTotal));

Ahora los precios si están correctos:

Subtotal : 100,05 €
Discount : 10,00 €
Total : 90,05 €
Tax : 4,50 €
Tax+Total: 94,55 €

Para el otro caso en el que teníamos un error de precisión:

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.NumberFormat;

RoundingMode RM = RoundingMode.HALF_EVEN;
BigDecimal amount = new BigDecimal("0.70");
BigDecimal taxPercent = new BigDecimal("0.05");
BigDecimal tax = amount.multiply(taxPercent).setScale(2, RM);
BigDecimal taxedTotal = tax.add(amount).setScale(2, RM); 

NumberFormat money = NumberFormat.getCurrencyInstance(); 
System.out.println("Subtotal: "+ money.format(amount)); 
System.out.println("Tax: " + money.format(tax)); 
System.out.println("Tax+Total: " + money.format(taxedTotal));

Subtotal: 0,70 €
Tax: 0,04 €
Tax+Total: 0,74 €

Referencia:
http://www.javamexico.org/blogs/luxspes/por_que_usar_bigdecimal_y_no_double_para_calculos_aritmeticos_financieros
http://speleotrove.com/decimal/decifaq1.html#tzeros
http://www.mkyong.com/java/how-do-calculate-monetary-values-in-java-double-vs-bigdecimal/
http://blogs.oracle.com/CoreJavaTechTips/entry/the_need_for_bigdecimal
http://stackoverflow.com/questions/7539/please-explain-the-use-of-java-math-mathcontext/7561#7561
http://en.wikipedia.org/wiki/Floating_point

domingo, 1 de enero de 2012

Calendario Arch Linux 2012

Empieza un nuevo año y una de las cosas que primero hacemos es ver y obtener un calendario para poner encima de nuestra mesa. Hace unos días vi un calendario tematizado con Ubuntu. En un rato que he sacado he tenido tiempo de crear uno basado en Arch Linux y traducido al español. Así que aquí lo tenéis listo y esperando para imprimir, construirlo y ponerlo encima de vuestra mesa. En el paquete tenéis la versión SVG, PNG y PDF (200 KiB) lo podéis obtener mediante este enlace.

Calendario Arch Linux 2012


Si le cogeís gusto a la papiroflexia los modelos de papel tal vez os interese obtener este Cheat Cube tambén para nuestra distribución. Ahora Tux y el cheat cube van a tener un nuevo compañero :). En cuanto pueda imprimirlo le saco unas fotos.

¡Que empecéis bien el año!

Referencia:
Calendarios de ubuntu para imprimir del 2012
http://spreadubuntu.org/es/node/751