MongoDB y Java usando Morphia

Como todos los que leen saben, soy un fiel y entusiasta usuario de MongoDB.

Actualmente estoy desarrollando un sistema Web para la universidad de la que fui alumno (soy egresado ya :D ), usando Java y MongoDB.

Si ya han buscado información, seguramente saben que para insertar documentos se tiene que usar el “coleccion.put(“Nombre”, nom)”. Y si bien funciona… no es muy bonito que digamos.

En VB .NET (también hago aplicaciones con Mongo en .NET) para guardar documentos simplemente enviaba una clase directamente y el driver se encarga solito de serializar la clase.

Pero en Java no encontraba por ninguna parte como hacer esto… Así que buscando y buscando, llegué a la solución usando una librería llamada Morphia 

Entonces, supongamos que tenemos una clase llamada Alumno con lo típico (Id, Rut, Nombre, Fecha_Registro), y la creamos de la siguiente manera:

import com.google.code.morphia.annotations.Entity;
import com.google.code.morphia.annotations.Id;
import java.util.Date;
import org.bson.types.ObjectId;

@Entity
public class Alumno {
    @Id private ObjectId id;
    private String Nombre,
            Rut_L,
            Pass;
    private Date Registro;
    private Integer Rut;

//Setters y Getters
}

Con esto tenemos lo necesario. Morphia se encarga de mapearlo al anotar el “@Entity” sobre la clase.

Ahora creamos un nuevo alumno y le metemos los datos. Algo así:

private Boolean NuevoUsuario(Integer _id, String nom, String app, String apm,
            String rut, String pass){
            Alumno a = new Alumno();
            a.setNombre(nom + " " + app + " " + apm);
            a.setPass(pass);
            a.setRut(_id);
            a.setRut_L(rut);
//...

Tenemos listo nuevo alumno, y seguimos con Morphia para que se encargue de guardar el objeto en la BD

            Morphia morphia = new Morphia();
            morphia.map(Alumno.class);
            Datastore ds = morphia.createDatastore(MongoConnection.getInstance().getConnection(),
                    MongoConnection.getInstance().getDatabase().getName());
            ds.save(a);

Como se ve, lo primero es mapear la instancia con la clase que queremos ingresar. Luego usamos un Datastore (interfaces para leer, actualizar o guardar la info) con la conexión a Mongo y el nombre de la BD que queremos usar (OJO que estoy usando una singleton). Por último, guardamos al alumno.

Con esto el código queda más elegante :D y la podemos ver en la shell con esta estructura.

Para leer, es igual de simple

            Morphia morphia = new Morphia();
            Datastore ds = morphia.createDatastore(MongoConnection.getInstance().getConnection(),
                    MongoConnection.getInstance().getDatabase().getName());
            Alumno a = ds.find(Alumno.class, "Rut", u).get();

Si se fijan, es lo mismo. En la 3º línea definimos el cómo se comportará el Datastore y por cuál parámetro vamos a buscar.

Eso si, el Datastore.find() devuelve un List, a menos que usemos el .get() que devuelve el primer resultado que encuentre (por lo que los controles de si se repite o no un documento corre por cuenta nuestra). Si el find() no encuentra nada, devuelve un null.

Eso es todo :D

Dejo todos los archivos que ocupé en una carpeta en SkyDrive ;)

Links

Publicado en Java, MongoDB, Tutoriales | Etiquetado , , | Deja un comentario

Reportes con HTML y AJaX

Para un trabajo que estaba haciendo (si, el mismo de la entrada anterior) me pidieron agregar un módulo para generar órdenes de compra.

Lo agregué al programa como un ítem más, basándome en la estructura de las facturas (de hecho, era lo mismo… ) algo así ventana

Hasta ahí, nada nuevo. Se podría registrar en el sistema sin problemas… el problema era el traspasar eso a los reportes que usaban en la empresa 

Pensé en pasarlo a PDF… pero nunca lo había hecho, y no tenía tiempo como para aprender . Otra solución, era usar Crystal Reports, que ya había utilizado antes… pero iba a tener que instalarlo en el PC de la empresa (y lo que menos quiero es instalar cosas aparte en el PC -por eso usé SQLite-)

La última solución, crear un report en html y actualizar los datos con ajax :)

Primero, tenía que mover la info desde la aplicación a la página html. Para hacerlo, utilicé json con la librería de Newtonsoft.Json

La lógica es de cada uno, pero lo que hice algo así:

1. Crear 2 variables de clase, una con el contenido total de la info, y un array

Private json As New JObject
Private jarray_detalle As New JArray 

Ahora, cada vez que agrego una línea al detalle, hice esto:

Dim linea_detalle As New
linea_detalle.Add("cod_pedido_proveedor", Me.txt_cod_pedido.
linea_detalle.Add("producto", Me.combo_producto.GetItemText(Me.combo_producto.
linea_detalle.Add("cod_interno", Me.combo_producto.SelectedValue.
linea_detalle.Add("compra", Me.txt_compra.
linea_detalle.Add("cantidad", Me.num_cantidad.Value.
linea_detalle.Add("precio", Me.txt_precio.
linea_detalle.Add("total",
Me.jarray_detalle.Add(linea_detalle) 

Con palabras: un JObject para guardar la info de dicha línea. Agrego tooodos los datos. Por último, agrego la línea al JArray del detalle.

Para terminar con los datos, los últimos datos de la órden:

Me.json.Add("ID", Me.maxOC)
Me.json.Add("Emisor", Me.txt_emisor.Text)
Me.json.Add("Proveedor", Me.getDatosProveedor(Me.combo_proveedor.SelectedValue))
Me.json.Add("Detalle", Me.jarray_detalle)
Me.json.Add("Pago", Me.combo_tipo_pago.GetItemText(Me.combo_tipo_pago.SelectedItem))
Me.json.Add("Observacion", Me.txt_observacion.Text)
Me.json.Add("Calculos", Me.calculos) 

Me.maxOC y Me.getDatosProveedor son funciones que uso para rescatar datos desde la BD que no ingresé en la órden.
Ahora que tengo toda la info necesaria en el objeto JSON, necesito guardarla en un archivo local de texto.
Simple con ésta función:

Private Function guardar(ByVal info As String) As Boolean
    Dim bAns As Boolean = False
    Dim objReader As StreamWriter
    Try
        objReader = New StreamWriter("datos.js")
        objReader.Write(info)
        objReader.Close()
        bAns = True
    Catch Ex As Exception
        MessageBox.Show(Ex.Message)
    End Try
    Return bAns
End Function 

Esto se guarda en la misma carpeta, y la estructura es así:

{
  "ID": 51,
  "Emisor": "Mario Cares",
  "Proveedor": {
    "Rut": "1234567",
    "Nombre": "Proveedor",
    "Direccion": "Direccion proveedor",
    "Correo": "mail@proveedor.cl",
    "Telefono": "(57) 123456"
  },
  "Detalle": [
    {
      "cod_pedido_proveedor": "10939",
      "producto": "Lustra muebles",
      "cod_interno": "101",
      "compra": "caja X 40",
      "cantidad": "5",
      "precio": "60",
      "total": 300
    },
    {
      "cod_pedido_proveedor": "100als",
      "producto": "Toalla Nova",
      "cod_interno": "301",
      "compra": "bolsas",
      "cantidad": "10",
      "precio": "400",
      "total": 4000
    }
  ],
  "Pago": "Contado",
  "Observacion": "Urgente",
  "Calculos": {
    "Recargo": "30",
    "Descuento": "40",
    "Neto": "4300",
    "IVA": "817",
    "Total": "5117"
  }
}

listo !
Terminamos con la parte del programa de escritorio, ahora abrimos la página plantilla y la cargamos con los datos.
Decir que a cada campo le asigné un ID para poder identificarlo (por ejemplo ) y en relación a eso asigno los valores.
Uso la función $.getJSON() de jQuery, quedando algo como esto:

$(document).ready(function()
{
	try{
		$.getJSON("datos.js", function(json) {
                        document.getElementById("id").innerText = json.ID;
			document.getElementById("emitidax").innerText = json.Emisor;
			document.getElementById("proveedor").innerText = json.Proveedor.Nombre;
			document.getElementById("rut").innerText = json.Proveedor.Rut;
			document.getElementById("direccion").innerText = json.Proveedor.Direccion;
			document.getElementById("telefono").innerText = json.Proveedor.Telefono;
			document.getElementById("mail").innerText = json.Proveedor.Correo;
			document.getElementById("pago").innerText = json.Pago;
			document.getElementById("observacion").innerText = json.Observacion;
			document.getElementById("recargo").innerText = json.Calculos.Recargo;
			document.getElementById("descuento").innerText = json.Calculos.Descuento;
			document.getElementById("neto").innerText = json.Calculos.Neto;
			document.getElementById("iva").innerText = json.Calculos.IVA;
			document.getElementById("total").innerText = json.Calculos.Total;
			for (z in json.Detalle){
				var x = document.getElementById("detalle").insertRow(1);
				var a = x.insertCell(0);var b = x.insertCell(1);var c = x.insertCell(2);
				var d = x.insertCell(3);var e = x.insertCell(4);
				var f = x.insertCell(5);var g = x.insertCell(6);
				a.innerHTML = json.Detalle[z].cod_pedido_proveedor;
				b.innerHTML = json.Detalle[z].producto;
				c.innerHTML = json.Detalle[z].cod_interno;
				d.innerHTML = json.Detalle[z].compra;
				e.innerHTML = json.Detalle[z].cantidad;
				f.innerHTML = json.Detalle[z].precio;
				g.innerHTML = json.Detalle[z].total;
			}
		});
	}catch(ex){
                //No es muy refinado, pero me indica el error al principio xD
		document.getElementById("id").innerText =ex.toString();
	}
}); 

Y eso es todo 8)

Lo he probado en Chrome y en IE. En Chrome no funciona y en IE corre a la perfección :) Como en la empresa usan IE… me basta con eso ;)

Publicado en Aplicación, JavaScript, SQLite, Tutoriales, VB, Windows | Deja un comentario

Decimales en SQLite y VB .NET

Entrada corta :)

Estoy haciendo un sistema de inventario para una empresa. Algo simple (no tiene muchas prestaciones que digamos), y por lo mismo decidí usar SQLite para almacenar la info.

Entre otras cosas, tengo una tabla con valores decimales (REAL) en SQLite.

-- Describe INGRESOS
CREATE TABLE ingresos (
    "ingresos_pk" INTEGER PRIMARY KEY AUTOINCREMENT,
    "ingresos_producto" INTEGER,
    "ingresos_fecha" TEXT,
    "ingresos_precio_un" INTEGER,
    "ingresos_cantidad" INTEGER,
    "ingresos_pm" REAL,
    "ingresos_factura" INTEGER
)

Como ven, ingresos_pm es un REAL que tiene decimales. Hasta ahora todo bien.

Cuando quería ingresar la info desde vb .net , lo hice con un Double. Algo así

Dim saldo As Integer = reader.GetInt32(1) + Integer.Parse(j.Item("Unidades").ToString)
Dim entrada As Integer = reader.GetInt32(0) + Integer.Parse(j.Item("Total").ToString)
Dim pmp As Double = entrada / saldo
Dim sentencia As String = "INSERT INTO ingresos (ingresos_producto, ingresos_fecha, " & _
    "ingresos_precio_un, ingresos_cantidad, ingresos_pm, " ingresos_factura) VALUES(" & _    
    j.Item("Producto").ToString & ", '" & Me.fecha.Text & "', " & j.Item("Precio").ToString  & _
    & ", " & j.Item("Unidades").ToString & ", " & pmp & ", " & pk_factura & ")"
cm = cn.CreateCommand
cm.CommandText = sentencia
cm.ExecuteNonQuery()
cm.Dispose() 

como cualquier persona noob lo haría…

Pero cada vez que lo ejecutaba, me levantaba una exception de que mi ingreso solo tenía 6 columnas, pero yo le enviaba 7 … Extraño 8O

Resulta que el Double iba con una coma “,” y por eso no me dejaba guardarlo :)

La solución ?? Usar parámetros

La sentencia SQL cambió a esto:

Dim sentencia As String = "INSERT INTO ingresos (ingresos_producto, ingresos_fecha, ingresos_precio_un, ingresos_cantidad, ingresos_pm, " & _
    "ingresos_factura) VALUES(" & j.Item("Producto").ToString & ", '" & Me.fecha.Text & "',  " & _
    " & j.Item("Precio").ToString & ", " & j.Item("Unidades").ToString & ", @pmp, " & _
    pk_factura & ")"
cm = cn.CreateCommand
cm.CommandText = sentencia
cm.Parameters.AddWithValue("@pmp", pmp)
cm.ExecuteNonQuery()
cm.Dispose() 

Notan el cambio ? en vez de concatenar tal cual el valor, lo dejé como una referencia (@pmp) y luego lo agregué como parámetro

Y eso fue todo :)

Publicado en Aplicación, SQLite, Tips, VB | Deja un comentario

Idioma de Apps en Alemán (Windows 8 CP)

El día de ayer, como muchos de ustedes, descargué e instalé Win 8 en mi máquina.

La instalé directo en mi equipo 8O , nada de usar máquinas virtuales.

Jugué un rato mironeando por aquí y por allá. Todo iba bastante bien, salvo por la configuración del teclado que estaba en English. Ps me fui al panel de control, agregué Español, y borré la de English… total no me servía.

Cuando entré a algunas Apps … estaban en Alemán x_X

El problema es que no me manejo mucho en ese idioma …

Para arreglar esto, simplemente tuve que agregar el idioma inglés nuevamente ¬¬

Y listo :) Cerrar las aplicaciones y volver a abrirlas hace que cargue todo sin problemas ;)

Publicado en Tips, Windows | Etiquetado , | 1 comentario

Actualizador de Archivos (Administrador)

Esta es una aplicación que estoy haciendo para usarla en mi trabajo.

Una de las pegas que tengo, es actualizar todas las versiones de sistemas antiguos en TODOS los PCs de los usuarios… es una tortura la verdad…

Por eso me dio por hacer  esto ;)

La idea era subirlo a BitBucket con Mercurial… pero para variar, me tienen bloqueada la conexión ¬¬

Así que, al menos por ahora, colgaré los archivos en mi SkyDrive.

Como dice el título, esta aplicación tiene 2 partes: Administrador y Cliente.

No pretendo escribir todo, que para eso tienen los fuentes. Esto va para la parte de leer y escribir en json, y leer propiedades de archivos.

Leer JSON

Todos los parámetros de esta aplicación se encuentran en un archivo (Configuraciones.json) El mio es así:

{
	"Configuraciones": {
		"Carpeta_Dropbox": "C:\\dropbox-tmp\\Dropbox\\Public\\",
		"Archivo_json": "Versiones.json",
		"Usuario_Dropbox": "62387943"
	},
	"Sistemas": [
		"CIFIMP", "Expedientes", "Certificados", "Convenios",
		"IQFIMP", "Giro", "OFPA", "Remuneraciones", "Patententes",
		"Tesorería"
	]
}

Tiene 2 campos: Configuraciones donde guardo los datos relevantes, y Sistemas que es un arreglo con todos los sistemas que puedo actualizar.

Para leer esto, desde el load de la aplicación tengo una llamada a función para leer el archivo y traspasarlo a un objeto json:

Private Function read_json_file(archivo As String) As JObject
        Try
            Dim json_txt As IO.StreamReader
            json_txt = IO.File.OpenText(archivo)
            Dim json As New JObject
            json = JObject.Parse(json_txt.ReadToEnd)
            json_txt.Close()
            Return json
        Catch ex As Exception
            Me.salida.Text = ex.ToString
            Return Nothing
        End Try
    End Function 

Recibo la ruta (absoluta) del archivo, lo abro en un StreamReader, y luego lo parseo en un objeto JObject. Ahora, para obtener la información:

Dim json_file As JObject
json_file = Me.read_json_file("Configuraciones.json")
Me.carpeta_dropbox = json_file.Item("Configuraciones").Item("Carpeta_Dropbox")
Me.archivo_json = json_file.Item("Configuraciones").Item("Archivo_json")
Me.usuario_dropbox = json_file.Item("Configuraciones").Item("Usuario_Dropbox")
Me.addCBSistemas(json_file.Item("Sistemas")) 

Para leer el array (que de paso estoy guardando en una columna combobox en una grilla) lo hago así:

Private Sub addCBSistemas(sistemas As JArray)
    Try
        Dim cmb As New DataGridViewComboBoxColumn()
        cmb.HeaderText = "Sistemas"
        cmb.Name = "cmb"
        cmb.MaxDropDownItems = 4
        For Each item In sistemas
            cmb.Items.Add(item.ToString)
        Next
        grilla.Columns.Add(cmb)
    Catch ex As Exception
        Me.salida.Text = ex.ToString
    End Try
End Sub 

Leer propiedades archivos

Esto lo metí dentro de una clase aparte (clase Archivo … xD)

Lo importante es esto Private info As System.IO.FileInfo y ya después es cosa de jugar:

Me.info = My.Computer.FileSystem.GetFileInfo(RUTA_AL_ARCHIVO)
Me.TAMAGNO = Me.info.Length / 1024
Me.CREACION = Me.info.CreationTime
Me.MODIFICACION = Me.info.LastWriteTime
'Para calcular MD5
Public ReadOnly Property getMD5 As String
    Get
        Dim md5 As String = Nothing
        Dim cadena As System.IO.FileStream
        Dim bait As [Byte]()
        Dim md5cryto As New System.Security.Cryptography.MD5CryptoServiceProvider
        cadena = System.IO.File.Open(Me.RUTA, IO.FileMode.Open, IO.FileAccess.Read)
        bait = md5cryto.ComputeHash(cadena)
        cadena.Close()
        md5 = BitConverter.ToString(bait)
        Me.MD5 = md5.Replace("-", "")
        Return Me.MD5
    End Get
End Property

Escribir JSON

Como dije anteriormente, cada info de los archivos lo guardo en un objeto de la clase Archivo, por lo que después recorro un arreglo que tengo y rescato los valores:

For Each a As Archivo In Me.listado
    Dim j As JObject = Me.make_jobect(a)
    If Not IsNothing(j) Then
        jarray.Add(j)
    Else
        Me.salida.Text = "Error al generar JObject"
    End If
Next

'y esta función para llenarlo
Private Function make_jobect(a As Archivo) As JObject
    Try
        Dim job As New JObject()
        job.Add("Nombre", a.NOMBRE)
        job.Add("Ruta", a.RUTA)
        job.Add("Creación", a.CREACION)
        job.Add("Modificación", a.MODIFICACION)
        job.Add("Tamaño", a.TAMAGNO)
        job.Add("MD5", a.MD5)
        job.Add("Url", a.URL)
        Return job
    Catch ex As Exception
        Me.salida.Text = ex.ToString
        Return Nothing
    End Try
End Function 

Y para guardarlo en un archivo

Private Function save_file_versiones(json_string As String) As Boolean
    Try
        Dim archivo As New String(Me.carpeta_dropbox & "\\" & Me.archivo_json)
        If Not Exists(archivo) Then
            Dim file As System.IO.FileStream
            file = System.IO.File.Create(archivo)
            file.Close()
        End If
        My.Computer.FileSystem.WriteAllText(archivo, json_string, False)
        Return True
    Catch ex As Exception
        Me.salida.Text = ex.ToString
        Return False
    End Try
End Function 

Y eso es todo. Obviamente, sl JObject debe pasarse a a texto. La conversión es tan simple como un jobject.toString

La aplicación aquí (lamento no poder subirla a BitBucket … pero bue… tendré que hacerlo desde mi casa ;) )

Publicado en Escritorio, Tutoriales, VB, Windows | Deja un comentario

Mini Entrada ! MongoDB en la nubecilla

Como bien saben, soy un fan de MongoDB, y aunque aún no lo manejo del todo, siempre estoy tratando de conocerlo mejor :D

Estoy haciendo una aplicación de control de versiones para ejecutables de los sistemas de la empresa en la que trabajo.

Y me dió por manejar los datos con Mongo. Me puse a buscar a ver si encontraba un hosting solo para la BD, y encontré 2 (vamos… no busqué mucho ajaja)

El primero es MongoHQ. Tenemos un máximo de  16MB con el plan de juego (para nada serio, solo pruebas)

El otro es MongoLab. Aquí tenemos hasta 240 MB. La creación de la cuenta es super rápido, y en menos de 2 minutos ya tienes tu BD :D

Mi BD

Publicado en MongoDB, Tips | Deja un comentario

Meta: Scala, BlueEyes y MongoDB

En mi colación, leí un artículo que me dejó con cara de WTF ! 8O (what the frak!) y dije: QUIERO HACER ESTO !

Pero solamente entendí menos de la mitad de todo lo que se dice en ese coso. Así que vamos a empezar por parte, ya que este tutorial lo hago para aprender yo mismo :)

Instalar y hacer algo en Scala, BlueEyes, Heroku y lo de Mongo Sobra :) Sigue leyendo

Publicado en Scala, Tutoriales | Etiquetado | Deja un comentario

Conexión Ultra Lenta a Internet en Ubuntu 11.10

Ya no avergüenza decirlo… soy un usuario de Ubuntu :)

Como la mayoría sabe, la última gran Distro Linux que me “cautivó” (por decirlo de alguna forma) fue Pardus Linux. Estuve cerca de 2 años usándola y eso para mi es muuucho tiempo. Fue una de las pocas que me daba todo lo que necesitaba, era segura, estable, rápida, y amiga de KDE como pocas :)

Pero hace unos días atrás se supo que quedaba descontinuada… No es gracia para nadie usar una distro virtualmente muerta. Si bien seguiría funcionando sin problemas, ya no tendría actualizaciones :(

Por eso empecé a buscar nuevas distros. Empecé por Arch… aún no la puedo instalar correctamente… Seguí con ArchBang, que es lo mismo pero con ventanas :D Se instaló bien… pero Pacman 4 me leseaba con los gpg (o pgp ?).

Descargué Opensuse y ni siquiera lo pude bootear… me daba un error así que no pude instalarlo. Al último ya todo rendido instalé Ubuntu para salir del paso.

A lo que iba (xD) la Internet era demasiada lenta… mucho y buscando por google encontré la solución :) con 2 sencillos comandos:

sudo rmmod iwlagn

Con esto se desconecta las redes.

sudo rmmod modprobe iwlagn 11n_disable=1

Con esto desconecta todo, y luego se reinicia.

Debo reconocer que no entiendo del todo qué hace cada comando, pero la cosa es que funcionó :)

Para no hacer esto cada vez que iniciamos, lo agregamos (el segundo comando) en el archivo /etc/modprobe.d/options.conf (que no existe) y yasta :D

Publicado en Tips, Ubuntu | 3 comentarios

The Lion King Rises

No puedo dejar pasar esto…

Y es que me da un escalofrío cada vez que lo veo… incluso mayor que cuando veo el original.

Publicado en Uncategorized | Etiquetado | Deja un comentario

Eliminar credenciales Windows

Un pc aquí en la pega funciona como servidor. Me dio por poner el servidor de MongoDB adentro, cosa que todos entráramos aquí.

Como usuario, tenía “Administrador” y me fijé que NO tenía contraseña. Tonces entré y le puse guardar credenciales porque, se suponía, no necesitaba nada más.

Resulta que SI necesitaba una contraseña… aunque no se por qué… y cuando entraba

Sin acceso a la red

Sigue leyendo

Publicado en Tips, Windows | Deja un comentario