Translate

lunes, 7 de noviembre de 2011

Eclipse cumple 10 años

El 5 de noviembre del 2001 fue liberada la primera versión de Eclipse, desde ese momento hasta hoy creció a pasos agigantados; dándonos una IDE optima de muy buena calidad. Nada más para decir, simplemente Feliz cumpleaños.


Dejo links:


Gosu

Gosu es un lenguaje que corre sobre la jvm, y tiene las siguientes características:

  • 100% orientado a objetos
  • tipado estático
  • es imperativo
  • 100% compatible con java
  • inferencia de tipos
  • soporta closures
  • generic simplificados
  • y con licencia Apache 2.0!


Veamos un ejemplo:


// Declare some data
var minLength = 4
var strings = { "yellow", "red", "blue" }

// Slice and dice the data using blocks
print( strings.where( \ s -> s.length() >= minLength )
              .sort()
              .join( ", " ) )

// Use standard java classes
var someFile = new java.io.File( "SomeFile.txt" )

// But with shiny new methods
someFile.write( strings.join( "\n" ) )


Dimos un pequeño vistazo a este lenguje, dejo links:

http://gosu-lang.org/
http://gosu-lang.org/intro.shtml
http://gosu-lang.org/examples.shtml

sábado, 5 de noviembre de 2011

Spring Insight

Spring Insight es una tecnología la cual da visibilidad del rendimiento en tiempo de ejecución de la aplicación.

Las pruebas de estrés de una aplicación por lo general son lentas. Mediante la combinación de Spring inSigth con sus herramientas de testing  (tal como JMeter), se puede ver no sólo que direcciones URL son lentas, sino porque y descubrir la forma de acelerarlos.



Dejo unos screenshot:





Dejo links:

http://www.springsource.org/insight
http://static.springsource.com/projects/tc-server/6.0/devedition/cinintro.html

Configurar spring para usarlo con anotaciones

Para configurar spring para que funcione a base de anotaciones es necesario crear el archivo applicationContext.xml de spring y lo vamos a guardar en WEB-INF si es una aplicación web y queremos usar spring como contexto:

  
        
         

Luego podemos configurar nestros beans con anoteciones de la siguiente manera, primero creamos la interfaz:

package com.ejemplo;

/**
 * @author emanuel
 *
 */
public interface HelloWorldService {
 
 public String convertToUpperCase(String word);

}

Y luego una clase que lo implemente:

package com.ejemplo;

import org.springframework.stereotype.Service;

/**
 * @author emanuel
 *
 */
@Service
public class HelloWorldServiceImpl implements HelloWorldService {

 @Override
 public String convertToUpperCase(String word) {
  return word.toUpperCase();
 }
}


Con @Service estamos indicando a spring es un servicio. Tambien podemos hacer @Autowired para que spring injecte por tipo, de igual forma que lo hace cuando configuramos por xml. Por ejemplo si deberiamos configurar un manager o action con anotaciones podemos hacer lo siguiente:

package com.ejemplo;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;

/**
 * @author emanuel
 *
 */
@Component("helloWorld")
@Qualifier("helloWorld")
@Scope("request")
public class HelloWorldBean {
 
 private String name;
 
 @Autowired
 private HelloWorldService helloWorldService;
 
 public void setHelloWorldService(HelloWorldService helloWorldService) {
  this.helloWorldService = helloWorldService;
 }

 public String convertNameToUpperCase() {
  name = helloWorldService.convertToUpperCase(name);
  return "success";
 }

 public String getName() {
  return name;
 }

 public void setName(String name) {
  this.name = name;
 }
    
}


Es muy comodo y elegante, la desventaja es que si quiero cambiar una dependencia debo recompilar, que creo que no es un gran problema. Es una alternativa genial!

jueves, 3 de noviembre de 2011

Probar Javascript con jsfiddle.net

Cuando tenemos que probar algo en Javascript es muy fácil tomamos un blog de nota hacemos una pagina que nos permita probar la función que necesitamos. Pero si usamos alguna librería Javascript se pone más complicado.  
En  ese caso es mucho más recomendable un servicio como el que provee esta pagina:


jsfiddle.net/


En el cual podemos probar nuestro html y Javascript. El código puede ser compartida con otros, incrustado en un blog, etc. Con este enfoque, los desarrolladores de JavaScript pueden aislar fácilmente los errores. 


Muy útil!


Dejo link:
http://doc.jsfiddle.net/

miércoles, 2 de noviembre de 2011

Actores con Akka

La concurrencia se puede manejar de dos formas a travez de hilos o thread como c++ y java o por medio de actores como erlang y scala. El modelo de actores es un modelo de concurrencia computacional que trata a los "actores" como los primitivos universal de la computación digital en paralelo: en respuesta a un mensaje que recibe, un actor puede tomar decisiones locales, crear más actores, envía más mensajes, y determinar cómo responder al siguiente mensaje recibido.

Si buscamos en la wikipedia dice lo siguiente:

En informática, el modelo de actor es un modelo matemático de cálculo simultáneas que trata a los "actores", como los primitivos universales de la computación digital simultáneas: en respuesta a un mensaje que recibe,un actor puede tomar decisiones locales, crear más actores, enviar más mensajes, y determinar cómo responder a la siguiente mensaje recibido. El modelo de actor se originó en 1973.  Se ha utilizado tantocomo un marco para una comprensión teórica de la computación, y como la base teórica para variasaplicaciones prácticas de los sistemas concurrentes. La relación de la modelo para otros trabajos se discute enla indeterminación en el cálculo simultáneo y el modelo de actor y cálculos proceso. Toma tu torta!!

Akka es un framework java que nos brinda este modelo en el lenguaje java. Permitiéndonos manejar la concurrencia de forma más simple como lo hace scala o erlang.

Veamos un ejemplo:

// server code
class HelloWorldActor extends UntypedActor {
  public void onReceive(Object msg) {
    getContext().tryReply(msg + " World");
  }
}

remote().start("localhost", 2552).register(
  "hello-service",
   actorOf(HelloWorldActor.class));

// client code
ActorRef actor = remote().actorFor(
  "hello-service", "localhost", 2552);
Object res = actor.ask("Hello").get();



Como podemos ver en ejemplo podemos hacer un manejo de actores de forma remota.  Akka Utiliza el modelo del actor junto con la memoria transaccional de software que elevar el nivel de abstracción y proporcionar una mejor plataforma para construir aplicaciones concurrentes correcta y escalable. A la vez es tolerante a fallos dado que fue concedido con tecnología Let it crash/Embrace failure. Akka es de código abierto y disponible bajo la licencia Apache 2. A la vez esta basado en scala y provee una api para este lenguaje, escrita en este lenguaje.

Tiene integración con Spring, soporta OSGI, se integra con Apache Camel. Solo falta que te cocine y te lave la ropa!

Seguramente vamos a seguir escribiendo sobre este framework, dado que esta muy bueno!

Dejo links:
http://en.wikipedia.org/wiki/Actor_model
http://akka.io/
http://akka.io/docs/
http://akka.io/docs/akka-modules/1.1.3/modules/spring.html

lunes, 31 de octubre de 2011

Netty

Netty es un framework de Jboss que provee un manejo asíncrono en aplicaciones web, un framework ideal para hacer comet.

Netty es un cliente NIO infraestructura de servidor que permite el desarrollo rápido y sencillo de aplicaciones de red, tales como servidores de protocolo y los clientes. Simplifica y agiliza la programación de la red tales como TCP y UDP socket servidor.

"Rápido y fácil" no significa que una aplicación resultante sufrirá un mantenimiento o un problema de rendimiento. Netty ha sido diseñado cuidadosamente con las experiencias obtenidos de la implementación de una gran cantidad de protocolos como FTP, SMTP, HTTP, etc.Como resultado, Netty ha logrado encontrar una forma de lograr la facilidad de desarrollo, rendimiento, estabilidad y flexibilidad sin compromiso.

Mas adelante vamos a probar este framework.

Dejo links:

http://www.jboss.org/netty
http://www.jboss.org/netty/documentation.html
http://docs.jboss.org/netty/3.2/guide/html_single/index.html

domingo, 30 de octubre de 2011

Apache Mina y Apache AsyncWeb

Mediante una serie de técnicas llamadas Comet, puedes hacer una aplicación que envíe datos al usuario en tiempo real; es decir, que el navegador mantenga la conexión siempre abierta y reciba continuamente nuevos datos cuando los haya. Para servidores y aplicaciones clásicas que no estén preparadas para mantener muchas conexiones, la forma más sencilla es solicitar desde el navegador un cada X segundos nueva información (polling). Si tenemos muchos usuarios a la vez abriendo conexiones y haciendo peticiones a la BD nos encontramos con que nuestro servidor no da más de sí y deja de atender peticiones. Un ejemplo de polling clásico sería realizar peticiones mediante AJAX a un script PHP que devuelve nuevos datos en JSON cada 3 segundos y actualiza la tabla de novedades.

En el desarrollo web, Comet es un neologismo para describir un modelo de aplicación web en el que una petición HTTP mantenida abierta permite a un servidor web enviar datos a un navegador por Tecnología Push, sin que el navegador los solicite explícitamente. Comet es un término paraguas de múltiples técnicas para conseguir esta interacción. Todos estos métodos confían en características incluidas por defecto en navegadores, como JavaScript, en lugar de sobre plugins no disponibles por defecto. Existen frameworks en java que nos permiten hacer coment tenemos a Netty de Jboss, Atmosphere y Apache Mina.

Vamos a ver como funciona y nos permiten hacer coment Apache Mina. Apache Mina es un framework que nos permite hacer aplicaciones escalables y performantes basadas en network. Este framework provee una api asincrona para varios tipos de transportes y protocolos tcp/ip o UDP/ip via Java Nio.

Apache AsyncWeb que es parte de Apache Mina, rompe con la forma petición-respuesta de los servidores webs más usados. Esto le permite ser altamente escalable y capaz de soportar un rendimiento muy alto incluso en escenarios de alto procesamiento de latencia.
Una Api simple permite crear fácilmente servicios asincronos y integración con spring permite una configuración simple con gran flexibilidad. AsyncWeb permite también aplicar filtros a todas las requests.

Dejo links:
http://mina.apache.org/
http://mina.apache.org/asyncweb/

martes, 25 de octubre de 2011

Muere John McCarthy, pionero de la inteligencia artificial y padre de Lisp

El Lisp (o LISP) es una familia de lenguajes de programación de computadora de tipo multiparadigma con una larga historia y una sintaxis completamente entre paréntesis. Este lunes este lenguaje esta de luto dado que su creador John McCarthy murió. Copio un trozo de una noticia:

El lunes fallecía en Boston, a los 84 años, uno de los grandes pioneros de la industria de la computación: John McCarthy fue el primer ingeniero que habló del término "inteligencia artificial", en 1956, y también fue uno de los primeros que sugirió, en los años sesenta, que las aplicaciones informáticas podrían llegar a ser vendidas como un servicio, tal y como ocurre con el gas o la electricidad. McCarthy es la tercera gran figura del mundo de la tecnología que fallece en las últimas semanas, después de las muertes de Steve Jobs, el fundador de Apple, y Dennis Ritchie, creador del lenguaje de programación C.

McCarthy se unió a la facultad de Stanford en 1962, tras pasar cortos periodos en Princeton, Dartmouth y el MIT. Se retiró en 2000 tras recibir varios reconocimientos, como el Premio Turing en 1972 y la Medalla Nacional de las Ciencias en 1991.

Dejo Links:

http://www.publico.es/ciencias/403365/muere-john-mccarthy-pionero-de-la-inteligencia-artificial
http://www.lavanguardia.com/tecnologia/20111025/54236811431/muere-el-padre-de-la-inteligencia-artificial-moderna-john-mccarthy.html
http://es.wikipedia.org/wiki/John_McCarthy

sábado, 22 de octubre de 2011

Cache de Hibernate

Generalmente todos los cache se basan en almacenar objetos en memoria para acelerar accesos posteriores, pero debemos aclarar que en Hibernate hay dos tipos de cache: el Primer Nivel y el Segundo Nivel.

Cache de Primer Nivel

 Es el que mantiene automáticamente Hibernate cuando dentro de una transacción interactuamos con la base de datos, en éste caso se mantienen en memoria los objetos que fueron cargados y si mas adelante en el flujo del proceso volvemos a necesitarlos van a ser retornados desde el cache, ahorrando accesos sobre la base de datos. Lo podemos considerar como un cache de corta duración ya que es válido solamente entre el begin y el commit de una transacción, en forma aislada a las demás. Hibernate lo maneja por defecto, no hay que configurar nada, si por alguna razón queremos deshabilitar o evitar el uso del cache, podemos usar un tipo especial de session: StatelessSession, se obtiene de la sessionFactory con el método openStatelessSession(). Se usa en el caso de los procesos batch, por ejemplo cuando se tiene que hacer inserts o updates masivos, así se evita que cada vez que se hace el save de un objeto, el mismo se quede en memoria y en el correr del proceso se produzca un error del tipo OutOfMemoryError. La StatelessSession no interactúa con el Cache de Primer Nivel ni con el Cache de Segundo Nivel, es casi como si se utilizara JDBC directamente.

Cache de Segundo Nivel

El Cache de Segundo Nivel permite ir varios pasos mas adelante en la mejora de la performance. La diferencia fundamental es que éste tipo de cache es válido para todas las transacciones y puede persistir en memoria durante todo el tiempo en que el aplicativo esté online, lo podríamos considerar como un cache global. Para habilitar el Cache de Segundo Nivel hay que realizar lo siguiente:
1. Seleccionar un Proveedor de Cache. Por ejemplo EhCache.
2. Agregar en el hibernate.cfg.xml los siguientes properties:

 
 org.hibernate.cache.EhCacheProvider
 true
3. Poner en el classpath del aplicativo el archivo de configuración ehcache.xml, según las instrucciones del proveedor.
4. Agregar en el mapping de las clases que se queren seleccionar como "cacheables" la siguiente entrada:

Hibernate define tres niveles de cache que determinan el aislamiento:

  • transactional: Garantiza un nivel de aislamiento hasta repeatable read. Es el nivel más estricto. Solamente se puede utilizar en clusters, es decir, con cachés distribuidas. 'read-write: Mantiene un aislamiento hasta el nivel de commited.
  • nonstrict read-write: No ofrece garantía de consistencia entre el caché y la base de datos. Es una es'trategia ideal para almacenar datos que no cambian habitualmente y que no sean demasiado críticos.
  • read-only: Es la estrategia de concurrencia menos estricta. Recomendada para datos que nunca cambian.

Otro tema importante es definir qué entidades se van a "cachear", los candidatos naturales son por ejemplo las clases que representan: provincias, países, monedas o similares. Hay que tener en cuenta que cuando se tienen relaciones one-to-many hacia éstas entidades, se debe configurarlas como fetch=select, no como fetch=join porque si no Hibernate va a "levantar" la relación haciendo un join en lugar de intentar obtener el objeto desde el cache. Información general

Ehcache se integra fácilmente con la hibernate. Gavin King, el responsable del modo de hibernate, es también un confirmador al proyecto EHCache. Esto asegura EHCache seguirá siendo un caché de primer nivel para la hibernate. Configuración de EHCache para Hibernate es simple. Los pasos básicos son:

  • Descargar e instalar EHCache en su proyecto
  • Configurar EHCache como un proveedor de memoria caché en la configuración de su proyecto Hibernate.
  • Configurar almacenamiento en caché de segundo nivel en la configuración de su proyecto Hibernate.
  • Configuración de Hibernate de caché para cada entidad, o la consulta que desea almacenar en caché.
  • Configurar ehcache.xml como sea necesario para cada entidad, colección o consulta configurado para almacenar en caché.


Maven
Configurar o añadir el siguiente repositorio en el pom:


   terracotta-releases
   http://www.terracotta.org/download/reflector/releases
   true
   false

Configurar o añadir el módulo del núcleo ehcache definido por la siguiente dependencias (pom.xml):

   net.sf.ehcache
   ehcache-core
   ${ehcacheVersion}

Si está configurando Hibernate y EHCache con terracotta, agregar las siguientes dependencias para su construcción (pom.xml):

   net.sf.ehcache
   ehcache-terracotta
   ${ehcacheVersion}



   org.terracotta
   terracotta-toolkit-${toolkitAPIversion}-runtime
   ${toolkitVersion}

Configurar EHCache como el proveedor de caché de segundo nivel

Para configurar EHCache como caché de segundo nivel de Hibernate, se debe configurar hibernate de la siguiente manera el archivo hibernate.cfg.xml:
Agregar la siguiente propiedad:

         net.sf.ehcache.hibernate.EhCacheRegionFactory
Para la creación de la instancia,

         net.sf.ehcache.hibernate.SingletonEhCacheRegionFactory
Para forzar a Hibernate a utilizar un singleton de EHCache CacheManager. Hibernate 3,0 a 3,2 uso:
         
         net.sf.ehcache.hibernate.EhCacheProvider
  
Para la creación de la instancia, o

         net.sf.ehcache.hibernate.SingletonEhCacheProvider

Para forzar a Hibernate a utilizar un singleton EHCache CacheManager.
        
         net.sf.ehcache.hibernate.SingletonEhCacheProvider
  

Habilitar caché de segundo nivel y la configuración de la caché de consultas
         
         net.sf.ehcache.hibernate.EhCacheProvider
  

Además de configurar la configuración de caché de segundo nivel de proveedores, usted tendrá que activar el caché de segundo nivel (por defecto está configurado en off - "falso" - por Hibernate). Esto se hace mediante el establecimiento de la siguiente propiedad en la configuración de su hibernación:

true
También es posible que desee activar la caché de consultas de Hibernate. Esto se hace mediante el establecimiento de la siguiente propiedad en la configuración de su hibernate config:

true

Configurar Hibernate Entidades de utilizar Segundo caché a nivel

Además de la configuración de la hibernación para uso de la caché de segundo nivel, Hibernate también se debe activar la caché de entidades, colecciones y consultas. Por ejemplo, para habilitar las entradas de caché para el com.somecompany.someproject.domain.Country se debe agregar lo siguiente al mapeo de hibernate:


...


Para habilitar el almacenamiento en caché, agregue el siguiente elemento.

Donde read-write|nonstrict-read-write|read-only es el tipo de cache.
Por ejemplo:


 
...



Esto también puede lograrse mediante la anotación @ caché, por ejemplo,

@Entity @Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
public class Country { ... }

Definición de las estrategias de caché diferente

De sólo lectura: Cachés de datos que no se actualiza.

No estricta-lectura-escritura:Cachés de datos que a veces se actualiza sin bloqueo de la memoria caché. Si el acceso simultáneo a un elemento es posible, esta estrategia de concurrencia no garantiza que el producto devuelto de la caché es la última versión disponible en la base de datos. Configurar el tiempo de espera de caché en consecuencia.

De lectura y escritura: Cachés de datos que a veces se actualiza la vez que mantiene la semántica de "lectura confirmada" nivel de aislamiento. Si la base de datos está establecida en "lectura repetible", esta estrategia de concurrencia casi mantiene la semántica. De aislamiento de lectura repetible se ve comprometida en el caso de escrituras simultáneas.


Query Cache

Para mejorar la performance y rendimiento de las aplicaciones podemos utilizar Query Cache.
Si lo que interesa es "cachear" el resultado exacto de una consulta, no objetos individuales. Por ejemplo, si tenemos un método en un DAO que retorna la lista de Países registrados en la base de datos, es muy probable que siempre retorne el mismo resultado ya que esa tabla no cambia a menudo, entonces es recomendable establecer la consulta como "cacheable".

Hay que tener en cuenta que el query cache solo almacena los identificadores de los objetos del resultado, es decir que lo debemos usar combinado con el Cache de Segundo Nivel. Los pasos serían:

1. Establecer el property hibernate.cache.use_query_cache=true en el hibernate.cfg.xml
2. Configurar la entidad Pais como "cacheable"
3. Establecer la consulta como "cacheable":



List paises = sess.createQuery("from Pais") .setCacheable(true) .list();


Por lo tanto, la primera vez que se ejecuta la consulta, se retorna la lista de Paises desde la tabla mediante un select, pero a partir de ese momento toda vez que se repita el query, el resultado va a ser retornado desde el cache, evitando la comunicación con la base de datos.

¿Que pasa si agrego un nuevo Pais?

Entonces el query dejaría de ser válido, solo si agregamos un nuevo Pais pasando por la session de Hibernate, el query se invalida automáticamente para que la próxima vez que se ejecute la consulta vuelva a obtener el resultado desde la base de datos. Es importante aclarar que el comportamiento anterior no se cumple si se inserta un Pais por afuera del aplicativo, es decir con un insert directo a la tabla, o si se tiene dos aplicativos separados que apuntan a la misma base de datos, en ese caso habría que usar JNDI para que todos compartan la misma SessionFactory.

Es recomendable usar el query cache solo en los casos en que una consulta se repite constantemente y la entidad resultado no cambia frecuentemente, por ejemplo: Países, Provincias, etc.

jdart

jdart es compilador a código java el nuevo lenguaje de google Dart. El objetivo es poder portar codigo dart a la plataforma. Actualmente se encuentra en desarrollo.
En la pagina del proyecto podemos ver un ejemplo del compilador:

main() {
  print("hello world");
}


Y esto compilaría a este código java:

public class test {
  public static void main(java.lang.String[]);
    Code:
       0: invokedynamic #18,  0             // InvokeDynamic #0:__main__:()V
       5: return        

  public static java.lang.Object __main__();
    Code:
       0: ldc           #21                 // String hello world
       2: invokedynamic #27,  0             // InvokeDynamic #1:print:(Ljava/lang/String;)V
       7: aconst_null   
       8: areturn       
}



Me parece una buena idea, todavía esta en desarrollo pero pinta lindo!
Dejo links:
http://code.google.com/p/jdart/
http://www.dzone.com/links/r/jdart_dart_to_jvm_bytecode_compiler_using_invoked.html
http://www.dartlang.org/

jueves, 20 de octubre de 2011

Recursos sobre Node.js

Node.js es un entorno JavaScript de lado de servidor que utiliza un modelo asíncrono y dirigido por eventos. Es muy interesante la propuesta del framework dejo un excelente manual para empesar:
http://www.rmunoz.net/introduccion-a-node-js.html

Dejo un libro de Node.js :
http://www.nodebeginner.org/index-es.html


domingo, 16 de octubre de 2011

Identidad del objeto en hibernate


Una aplicación puede acceder simultáneamente al mismo estado persistente en dos Sessiones diferentes. Sin embargo, una instancia de una clase persistente nunca se comparte entre dos instancias de Session. Por lo tanto, existen dos nociones diferentes de identidad:



Identidad de Base de Datos
foo.getId().equals( bar.getId() )

Identidad JVM
foo==bar

Para los objetos unidos a una Session en particular (por ejemplo, en el ámbito de una Session) las dos nociones son equivalentes y la identidad de la JVM para la identidad de la base de datos se encuentra garantizada por Hibernate. Mientras la aplicación acceda simultáneamente al "mismo" objeto (identidad persistente) en dos sesiones diferentes, las dos instancias serán realmente "diferentes" (identidad JVM). Los conflictos se resuelven usando un enfoque optimista y el versionado automático.

Este enfoque deja que Hibernate y la base de datos se preocupen de la concurrencia. Además provee la mejor escalabilidad, ya que garantizando la identidad en unidades de trabajo monohilo no necesitan bloqueos caros u otros medios de sincronización. La aplicación no necesita sincronizar sobre ningún objeto, siempre que se mantenga un solo hilo por Session.

Dentro de una Session la aplicación puede usar con seguridad == para comparar objetos. Sin embargo, una aplicación que usa == fuera de una Session, podría ver resultados inesperados. Esto podría ocurrir incluso en sitios algo inesperados. Por ejemplo, si pone dos instancias separadas dentro del mismo Set ambas podrían tener la misma identidad de la base de datos (por ejemplo, representar la misma fila). Sin embargo, la identidad JVM, por definición, no está garantizada para las instancias en estado separado.

El desarrollador tiene que sobrescribir los métodos equals() y hashCode() en las clases persistentes e implementar su propia noción de igualdad de objetos. Nunca se debería usar el identificador de la base de datos para implementar la igualdad. Use una clave de negocio, una combinación de atributos únicos, usualmente inmutables. El identificador de la base de datos cambiará si un objeto transitorio es hecho persistente. Si la instancia transitoria (usualmente junto a las instancias separadas) es mantenida en un Set, cambiar el código hash rompe el contrato del Set. Los atributos para las claves empresariales no tienen que ser tan estables como las claves principales de la base de datos, sólo tiene que garantizar estabilidad en tanto los objetos estén en el mismo Set.

Este no es problema de Hibernate, sino que simplemente se tiene que implementar la identidad y la igualdad de los objetos Java.


sábado, 15 de octubre de 2011

Para que la gente prueba smalltalk facilmente

Una forma fácil de probar Smalltalk por medio de la web es el siguiente sitio:

http://amber-lang.net/learn.html

Este sitio nos permite programar en Smalltak por medio de una consola web. Genial idea.