BlackBerry, un nuevo rumbo.

Había empezado a escribir esta entrada sobre Black Berry hace casi 15 días, cuando de repente empezaron a saltar las noticias sobre su posible venta, su ‘segura’ venta y ahora los rumores de que quizás pudiese tener más novias (como Google, Intel, LG o Samsung).

Así que me veo a obligar a reescribirla, para hablar sobre cuál podría haber sido su nuevo rumbo, a la espera de lo que suceda a partir de ahora.

BlackBerry Logo

BlackBerry

Un poco de historia.

La mayoría conocemos a BlackBerry por ser la empresa que integró la telefonía profesional en nuestras empresas con los servidores de correo y servicios de mensajería.

Hasta no hace muchos años, cuando iPhone acaba de llegar y Android aún tenía camino por recorrer, era de lo más habitual ver en nuestras empresas terminales de BlackBerry que nos proporcionaban acceso permanente a nuestro correo corporativo y calendario, además de los servicios de telefonía móvil, acceso a internet e incluso algunas aplicaciones útiles para el día a día.

Sin embargo, en apenas unos años y con la irrupción de los smartphones, BlackBerry ha perdido una importante cuota de mercado y ha dejado de ser el terminal por excelencia en las empresas.

Rediseñando BB.

Metida en una profunda crisis y con el afán de recuperarse, BB se metió de lleno a diseñar nuevos terminales con una nueva versión de su sistema operativo, con el afán de recuperar la confianza de sus antiguos clientes, dando lugar a su BB10 y terminal Z10 como buque insignia.

BlackBerry Z10

BlackBerry Z10

Sobre ello podéis leer este análisis en Xataka, donde queda claro que BB ha hecho un gran esfuerzo por ponerse al día y consiguiendo un muy buen producto.

Pero, el problema que tenía BB es el mismo que tiene hoy Microsoft con su Windows Phone (no dejéis de probarlo, os sorprenderá), y no es más que el haber llegado tarde a una batalla entre dos contendientes que tienen la mayor parte del mercado.

Pese a contar con un gran producto, con algunos puntos fuertes y una integración muy buena de nuestras cuentas en redes sociales y profesionales, a estas alturas era difícil convencer a los usuarios para volver a confiar en BB o simplemente en que merece la pena pagar por un Z10, cuando por el mismo precio tienes terminales con Android superiores.

Un posible camino.

A estas alturas, una vez ya casi realizada la venta y casi decidido el futuro de Black Berry, es difícil saber qué sucederá con esta marca y si quizás, como le pasó antes a Palm, terminará desapareciendo quedando solo en el recuerdo de algunos.

Pero quizás BB habría podido tener una oportunidad, de haber cambiado su estrategia en su momento.

Con iOS y Android dominando el mercado, la idea de intentar competir con su propio SO se antojaba algo difícil, ya no solo por tener que convencer a los usuarios si no por tener que convencer a los desarrolladores de aplicaciones para que programen para tu plataforma.

Por ello, y viendo movimientos como el de Amazon para sus nuevos Kindle, la opción podría haber pasado por decantarse por Android y haber aprovechado el éxito de esta plataforma.

¿Otro fabricante más para Android?… Pues sí y no.

Porque si bien existen ya muchos fabricantes, desde gama baja a alta, hay todavía un aspecto en el que nadie ha invertido.

Con las políticas BYOD a la orden del día en las empresas, donde cada vez es más habitual ver dispositivos de los trabajadores en el día a día, los departamentos de Sistemas corren para dar soporte y evitar los habituales problemas de seguridad.

Y ahí es donde BB podría haber ganado terreno, dedicando sus esfuerzos a proporcionar una versión profesional de Android, capaz de proporcionar un espacio personal y otro profesional dentro del mismo dispositivo.

Imaginar un Android, como el que muchos tenemos ya, donde tengamos nuestro espacio personal, aplicaciones, fotos, mensajería y correo… pero que a la vez nos permita mantener un segundo perfil profesional, aislado del anterior, desde el que podamos acceder a nuestro entorno de trabajo.

Entornos separados, aplicaciones separadas para prevenir el robo de información sensible, incluso en dispositivos dual-SIM el usar conexiones distintas para cada entorno, sería una idea atractiva para las empresas que intentan ser flexibles con las exigencias de sus empleados pero sin problemas de seguridad.

Y ahí BB podría haber aportado todo su conocimiento y experiencia en entornos empresariales, siendo capaces de ofrecer no solo esa versión de Android sino también todo el ecosistema necesario para que las empresas pudiesen integrarlo.

Aunque por desgracia, me temo que ahora mismo el futuro de BB está mucho más cerca de desaparecer como marca.

Sonar – Maven: A required class was missing

Me estoy pegando desde ayer para integrar nuestro actual proyecto con Sonar, para poder realizar pruebas de cobertura y mostrar estadísticas de infracciones de código, y tras la instalación de Sonar en local me he encontrado un problema al ejecutarlo las primeras veces.

Tras la instalación, al lanzar por primera vez Sonar con:

mvn sonar:sonar

obtenía errores al faltarme librerías, que no estaban en nuestro repositorio y he tenido que ir bajándome de MVNRepository, para luego instalarlas en nuestro Artifactory.

Tras incluir todas las librerías necesarias, al lanzar el comando me he encontrado con el siguiente error:

[ERROR] Failed to execute goal org.codehaus.mojo:sonar-maven-plugin:2.0:sonar
(default-cli) on project tbs: Execution default-cli of goal
org.codehaus.mojo:sonar-maven-plugin:2.0:sonar
failed: A required class was missing while executing
org.codehaus.mojo:sonar-maven-plugin:2.0:sonar:
Ljavax/persistence/EntityManagerFactory;

En principio no debería de producirse, ya que se supone que al descargar los JARs y subirlos, estos incluyen el pom con las dependencias sobre otras librerías.

Pero ha dado la casualidad de que para la librería plexus-classworlds-2.2.3 su pom está mal y necesita que incluyamos dos dependencias más: persistence-api-1.0 y javassist (yo he incluido la última versión: 3.12.1.GA).

De esta forma, el pom queda así:

  <dependencies>

    <dependency>

      <groupId>junit</groupId>

      <artifactId>junit</artifactId>

      <version>3.8.2</version>

      <scope>test</scope>

    </dependency>
    <dependency>
      <groupId>javax.persistence</groupId>
      <artifactId>persistence-api</artifactId>
      <version>1.0</version>

      <scope>compile</scope>

    </dependency>
    <dependency>
    <groupId>javassist</groupId>
    <artifactId>javassist</artifactId>
    <version>3.12.1.GA</version>

      <scope>compile</scope>

    </dependency>
  </dependencies>

Tenerlo en cuenta por si os encontráis con el mismo problema.

En caso de que la clase que os falte sea otra y no sepáis desde dónde se hace referencia, lanzar el comando en modo debug:

mvn sonar:sonar -X

Revisar las trazas y además del nombre de la clase que necesitáis, tomar nota de la clase donde se está invocando a la misma, como en este ejemplo:

A partir de aquí, primero tendréis que averiguar, tirando de Google, a qué librería pertenece la clase que os falta, y después en cuál de las que habéis incluido se encuentra la clase que la usa.

En mi caso la clase javax.persistence.EntityManagerFactory se encuentra en persistence-api-1.0.jar, así que lo busco en algún repositorio de Maven y lo subo a mi artifactory.

Y la clase que la requiere se encuentra en plexus-classworlds-2.2.3, así que me descargo el pom del Artifactory y lo modifico para incluir la dependencia que necesito, volviendo a subir el pom al Artifactory.

Una vez hecho, borro mi repositorio local, para forzar que se lo vuelva a descargar, y compruebo si necesito alguna dependencia más o ya funciona Sonar.

Un pequeño ejemplo con JAXB.

JAXB, acrónimo de ‘Java Architecture for Xml Binding‘, es un API para convertir objetos Java en xml y leer esos mismos xml para obtener objetos Java, que desde la versión 7 tenemos disponible en nuestros JDKs.

Recientemente nos surgió la necesidad, en uno de los proyectos en los que trabajo, de poder guardar ‘evidencias’ de objetos durante la ejecución de una serie de programas a modo de registro para poder analizar el comportamiento y evolución de una serie de datos calculados.

La primera idea para hacer esto sería el escribir un método ‘toString’ que nos devuelva los valores del objeto de tal forma que los podamos ir volcando a uno o varios ficheros, para luego poder analizarlos.

Pero fue esa misma necesidad de poder analizarlos posteriormente la que me hizo pensar en hacer algo más elaborado, de forma que no solo pudiésemos obtener una representación de cada objeto en un momento dado, si no también poder luego explotar esa información desde nuestro aplicación de análisis.

Así fue como decidí tirar de JAXB, ahora que se ha incorporado a Java 7, pensando en obtener una representación que no dependiese de formatos propios y fuese fácilmente explotable.

La ventaja de JAXB reside en su capacidad de realizar ‘marshal’ y ‘unmarshal’ de objetos Java de forma directa, mediante el uso de anotaciones para indicar qué campos son los que queremos incluir en el xml, de una forma rápida, sencilla y no dependiente de un esquema.

El no depender de un esquema nos aporta además la ventaja añadida de poder realizar cambios sobre los objetos sin necesitar de realizar cambios en el parser que usáramos para convertir a xml y viceversa.

Para ver lo sencillo que es, planteemos un ejemplo.

Supongamos que tenemos una Clase Empresa:

package com.art4software.java.jaxb.example.po;

import java.util.ArrayList;

import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlType;

import com.art4software.java.jaxb.example.MarshalClass;

@XmlRootElement
@XmlType (propOrder = { "nombreEmpresa", "idEmpresa", "direccion", "numEmpleados", "empleados" })
public class Empresa extends MarshalClass {

	private int idEmpresa;
	private String nombreEmpresa;
	private String direccion;
	private int numEmpleados;
	private ArrayList<Empleado> empleados;

	public int getIdEmpresa() {
		return idEmpresa;
	}

	@XmlElement
	public void setIdEmpresa(int idEmpresa) {
		this.idEmpresa = idEmpresa;
	}

	public String getNombreEmpresa() {
		return nombreEmpresa;
	}

	@XmlElement
	public void setNombreEmpresa(String nombreEmpresa) {
		this.nombreEmpresa = nombreEmpresa;
	}

	public String getDireccion() {
		return direccion;
	}

	@XmlElement
	public void setDireccion(String direccion) {
		this.direccion = direccion;
	}

	public int getNumEmpleados() {
		return numEmpleados;
	}

	@XmlElement
	public void setNumEmpleados(int numEmpleados) {
		this.numEmpleados = numEmpleados;
	}

	public ArrayList<Empleado> getEmpleados() {
		return empleados;
	}

	@XmlElement
	public void setEmpleados(ArrayList<Empleado> empleados) {
		this.empleados = empleados;
	}
}

Como podemos ver nuestra Empresa tiene Empleados:

package com.art4software.java.jaxb.example.po;

import java.util.Date;

import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;

import com.art4software.java.jaxb.example.MarshalClass;

@XmlRootElement(name="Empl")
public class Empleado extends MarshalClass{

	private int id;
	private String nombre;
	private String titulo;
	private boolean activo=false;
	private Integer numeroEmpl;
	private Date fechaAlta;

	public int getId() {
		return id;
	}

	@XmlElement
	public void setId(int id) {
		this.id = id;
	}

	public String getNombre() {
		return nombre;
	}

	@XmlElement
	public void setNombre(String nombre) {
		this.nombre = nombre;
	}

	public String getTitulo() {
		return titulo;
	}

	@XmlElement
	public void setTitulo(String titulo) {
		this.titulo = titulo;
	}

	public boolean isActivo() {
		return activo;
	}

	@XmlElement
	public void setActivo(boolean activo) {
		this.activo = activo;
	}

	public Integer getNumeroEmpl() {
		return numeroEmpl;
	}

	@XmlElement
	public void setNumeroEmpl(Integer numeroEmpl) {
		this.numeroEmpl = numeroEmpl;
	}

	public Date getFechaAlta() {
		return fechaAlta;
	}

	@XmlElement
	public void setFechaAlta(Date fechaAlta) {
		this.fechaAlta = fechaAlta;
	}

}

Si os fijáis usamos 3 anotaciones: XmlRootElement, XmlType y XmlElement.

La primera marca el elemento raíz de nuestra clase (en nuestro caso el nombre de la clase). Con XmlType y la propiedad ‘propOrder’ cambiamos el orden en que se escribirán los atributos en el xml resultante.

Finalmente usando XmlElement en el setter de los atributos que nos interesa que se incluyan en el xml, marcamos los campos de nuestro interés.

Si os fijáis, ambas clases heredan de una tercera clase: MarshalClass.

¿Y para qué?

En mi caso, dado que la acción de guardar ‘evidencias’ se realizará sobre clases distintas, con esta herencia puedo limitar a un tipo común el manejo de las clases a guardar, haciendo que hereden de dicha clase el método de guardado:

package com.art4software.java.jaxb.example;

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;

public class MarshalClass {

	public void generateXML (String nameFile) {

		try {
			File file = new File (nameFile);
			JAXBContext jc = JAXBContext.newInstance(this.getClass());
			Marshaller jaxbMarshaller = jc.createMarshaller();

			jaxbMarshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);

			jaxbMarshaller.marshal(this, new FileWriter(nameFile, true));

		} catch (JAXBException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
}

Si os fijáis en el código del método, que será común para todos, realizar el Marshal es tan sencillo como:

  1. Obtener un JAXBContext sobre la clase a representar en xml (en nuestro caso).
  2. A partir de este contexto crear un ‘Marshaller’
  3. Configurar el formato de salida.
  4. Invocar al método para escribir la clase a xml.

En mi ejemplo uso un FileWriter en lugar de un File (cuya declaración he dejado en el ejemplo aunque no se usa) porque así podría ir volcando todas las representaciones a un único fichero, donde se iría añadiendo el xml de cada clase en cada invocación.

Si usáramos el File, estaríamos machacando el contenido si usamos el mismo nombre de fichero, o generando un nuevo fichero por cada invocación usando nombres distintos.

Ahora, para ejecutarlo:

package com.art4software.java.jaxb.example;

import java.util.ArrayList;
import java.util.Date;

import com.art4software.java.jaxb.example.po.Empresa;
import com.art4software.java.jaxb.example.po.Empleado;

/**
 *
 * @author mvcarrillo
 *
 */
public class JAXBExample {

	/**
	 * @param args
	 */
	public static void main(String[] args) {

		marshallingExample();

	}

	/**
	 * Crea una empresa y 10.000 empleados.
	 */
	private static void marshallingExample () {

		long time = System.currentTimeMillis();
		System.out.println ("Inicio: " + new Date(time));
		Empresa cc = new Empresa ();
		cc.setIdEmpresa(1);
		cc.setDireccion("En la nube");
		cc.setNombreEmpresa("Art4Software");
		cc.setNumEmpleados(25000);

		ArrayList<Empleado> alCU = new ArrayList<Empleado> ();
		int init = 20000;
		for (int i=1;i<10000;i++) {
			Empleado cu = new Empleado ();
			cu.setId(i);
			cu.setActivo(true);
			cu.setNumeroEmpl(new Integer (init++));
			cu.setNombre("Empleado " + i);
			cu.setTitulo("SW Architect");
			cu.setFechaAlta(new Date(System.currentTimeMillis()));

			alCU.add(cu);
		}

		cc.setEmpleados(alCU);

		long time2 = System.currentTimeMillis();

		System.out.println ("Generacion: " + (time2-time) + " milisegundoss - Marshaling: " + new Date (time2));

		cc.generateXML("Art4Software-Datos.xml");

		long time3 = System.currentTimeMillis();

		System.out.println ("Fin: " + new Date(System.currentTimeMillis()) + " - Tiempo Total: " + (time3 - time) + " milisegundos");

	}
}

Para realizar la conversión de todos los objetos, tan solo necesitamos invocar al método sobre el objeto ‘Empresa’, sin tener que hacerlo por cada objeto del tipo ‘Empleado’ que pueda contener en el ArrayList.

Como podéis ver, hemos metido unas trazas para ver cuánto tiempo tarda en realizar la creación de los objetos y el volcado a xml, obteniendo los siguientes tiempos (con JDK 1.7u21, eclipse Indigo, en un PhenomII x6 1090T con 8GB RAM):

Inicio: Fri Jun 07 22:38:56 CEST 2013
Generacion: 29 milisegundoss – Marshaling: Fri Jun 07 22:38:56 CEST 2013
Fin: Fri Jun 07 22:38:57 CEST 2013 – Tiempo Total: 312 milisegundos

Menos de medio segundo es un tiempo realmente bueno para lo que necesitamos realizar.

Ahora, a partir de aquí podríamos crearnos una aplicación que cargase un xml, o los xml contenidos en un directorio para una fecha concreta, y obtuviese todos los objetos grabados de nuevo para analizar los resultados.

Por último, importante tener en cuenta la siguiente tabla con la equivalencia de tipos de datos:

JAXB - Tabla Datos

Correspondencia de datos por defecto.

Truco: Android, mala conexión inhabilitada.

Igual en algún momento alguno os encontráis con el mismo problema con el que me he encontrado yo hoy cuando de repente y tras mucho tiempo de funcionar sin problemas, vuestro móvil decide no conectarse a vuestra WiFi.

La única señal es ver en los ajustes de red, en las redes WiFi, que vuestro móvil intenta conectarse continuamente a vuestra red habitual sin éxito, hasta que finalmente os da un mensaje:

mala conexión inhabilitada

De momento la única solución pasa por cambiar la configuración por defecto, por DCHP, por configurar la IP de forma manual.

Poner una IP fija dentro del rango de las configuradas en vuestro router, los mismos servidores DNS configurados en vuestro router, y como puerta de enlace la IP del propio router.

Tras ello probar a conectar y volveréis a disfrutar de vuestra conexión WiFi habitual.

No he encontrado explicación oficial, aunque en los foros de HTCMania un usuario daba una solución definitiva (aunque yo no la he probado aún):

La solución es:

1. «Olvidar» la wifi en cuestión en el móvil
2. Desactivar la wifi
3. borrar todos los ficheros de la carpeta /data/misc/dhcp (yo lo hice con Root Explorer, supongo que es necesario ser root)
4. reiniciar, volver a activar la wifi, volver a poner el password de tu wifi, etc

A mí me pasaba y esto lo solucionó definitivamente.

Actualizaré cuando la haya podido probar y validar.

Actualizado:

Efectivamente con esto funciona, aunque hay que ser un poco más precisos con las instrucciones.

Los ficheros a borrar están en /data/misc/dhcp, y son:

  • dhcpcd-wlan0.lease
  • dhcpcd-wlan.pid

Para eliminarlos, siendo root en vuestro móvil, lo mejor es bajarse una aplicación de terminal (por ejemplo esta) , abrir una sesión y hacer:

$ su

Con esto nos pedirá otorgar permisos de superusuario (root), permitirlo para ser root.

#cd /data/misc/dhcp
#rm dhcpcd-wlan*

Ahora volvemos a la configuración de la WiFi, borramos nuestra red, volvemos a configurarla y debe funcionar de nuevo sin problemas.

Actualización – 26 de enero de 2014

Sois muchos los que dejáis comentarios mencionando que no encontráis los ficheros a eliminar en la ruta especificada.

Ante esto, dado que a mí no me ha sucedido y no puedo investigarlo, solo os puedo decir que os aseguréis de:

  • Acceder al directorio como usuario root (no olvidéis tener permisos de root y hacer el ‘su’ en la ventana de terminal).
  • Acceder a la ruta en la partición adecuada, muchos móviles traen la memoria principal particionada con dos particiones.
  • Si con el terminal no veis los archivos, descargar una aplicación como Root Explorer o Root Browser (la segunda es gratuita) para intentar acceder al directorio como root.
  • Probar a configurar una IP estática.
  • Si la IP estática no funciona, probar a cambiar el nombre y el canal de vuestra red en el router (según el modelo de router podéis encontrar información sobre cómo hacerlo buscando en Google) para que el teléfono la reconozca como una red distinta.

Para cualquier otro problema no os vamos a poder ayudar, dado que estas cosas requieren de probarlas en persona para poder discernir qué es lo que está ocurriendo y cómo solucionarlo.

Un saludo.