El documento presenta el framework Blaapps para desarrollar aplicaciones distribuidas. Blaapps es ligero, rápido y fácil de utilizar. Los módulos de Blaapps pueden extender sus funcionalidades mediante anotaciones. El documento explica cómo crear y utilizar módulos de Blaapps para añadir persistencia de datos y objetos remotos.
5. OBJETIVO: REDUCIR COSTES
Tareas Comunes: Aplicación
•Persistencia
•Colas de mensajes
•Seguridad Aplicación
•Conexiones
•...
Aplicación
Una empresa utiliza el servidor de aplicaciones para reducir costes de desarrollo.
El servidor de aplicaciones realiza tareas comunes para varias aplicaciones.
7. UN POCO DE HISTORIA…
Programación Estructurada
open file;
while (reading not finished) {
read some data;
if (error) { } Hardware
}
process read data;
1970's
1800-1960 1980's 1990's
La PE permitió dar instrucciones en un lenguaje más humano.
Se sigue trabajando con la máquina.
8. UN POCO DE HISTORIA…
Sistemas Operativos
open file;
while (reading not finished) {
read some data;
if (error) { } S.O. Hardware
}
process read data;
1970's
1800-1960 1980's 1990's
Con la difusión de los sistemas operativos el desarrollador se abstrae del Hardware.
9. UN POCO DE HISTORIA…
Programación Orientada a Objetos
S.O. Hardware
1980's
1800-1960 1970's 1990's
La POO permite crear abstracciones aún más cercanas a la forma de pensar humana.
10. UN POCO DE HISTORIA…
Frameworks
Framework
S.O. Hardware
1990's
1800-1960 1970's 1980's
La mayoría de las apps realizan las mismas tareas:
Conexión a base de datos, gestión de las acciones del usuario...
Un Framework implementa estas funciones para el desarrollador. El desarollador sólo se centra en su aplicación.
11. OBJETIVO: REDUCIR COSTES
Tareas Comunes: Aplicación
•Persistencia
•Colas de mensajes
•Seguridad Aplicación
•Conexiones
•...
Aplicación
Los servidores de aplicaciones son Frameworks.
De nuevo, el objetivo es reducir costes.
A parte de que se desarrolla menos código, desarrollar se hace más fácil, por tanto se necesitan menos expertos.
12. OBJETIVO: REDUCIR COSTES
Si mi plataforma es tan fácil de desarrollar, que hasta un mono puede aprenderla...
15. Muchas veces veo los Servidores de Aplicaciones como grandes dinosaurios: Grandes y pesados.
Tienen muchas funcionalidades, son muy robustos y por ello son ideales para aplicaciones empresariales...
17. BLAAPPS
• Ligero
• Rápido
• Fácil de utilizar
• Modular
Es ligero y muy rápido. (Arranca en menos de 3 segundos)
Es fácil de utilizar (Ahora lo veremos)
Y es flexible, puede aumentar de funcionalidad mediante módulos...
19. BLAAPPS CORE
Sistemas mínimos:
• Cargador de Módulos
• Configuración
• Registros
• Mensajería
• MBean Server
Blaapps está formado por 4 sistemas principales...
20. BLAAPPS MODULES
Funcionalidades extra:
• Objetos Remotos (RMI)
• Persistencia (JPA)
De momento hay desarrollados dos módulos...
21. ¿CÓMO SE USA?
Blaapps Core
Antes hemos comentado que Blaapps es fácil de usar, veámoslo...
22. @Module(
! name = "HiWorld",
! description = "An example module",
! version = @Version(revision=5) // 0.5.0.0
)
public class HiWorld {
! @Log
! private Logger log;
! @AfterDeployment
! public void sayHello() {
! ! log.info("Hello world!");
! }
! ...
}
Esto sería un Módulo de blaapps.
23. @Module(
! name = "HiWorld",
! description = "An example module",
! version = @Version(revision=5) // 0.5.0.0
)
public class HiWorld {
! @Log
! private Logger log;
! @AfterDeployment
! public void sayHello() {
! ! log.info("Hello world!");
! }
! ...
}
24. @Module(
! name = "HiWorld",
! description = "An example module",
! version = @Version(revision=5) // 0.5.0.0
)
public class HiWorld {
! @Log
! private Logger log;
! @AfterDeployment
! public void sayHello() {
! ! log.info("Hello world!");
! }
! ...
}
Inyección de dependencias
25. @Module(
! name = "HiWorld",
! description = "An example module",
! version = @Version(revision=5) // 0.5.0.0
)
public class HiWorld {
! @Log
! private Logger log;
! @AfterDeployment
! public void sayHello() {
! ! log.info("Hello world!");
! }
! ...
}
Ciclo de vida de un módulo.
26. blaapps
bin
blaapps-launcher.jar
conf
blaapps.properties
deploy
HiWorld.jar
lib
blaapps libraries
blaapps libraries
blaapps libraries
blaapps libraries
Meteríamos esa clase en blaapps/deploy/HiWorld.jar
27. $ cd blaapps/bin
$ java -jar blaapps-kernel-launcher.jar ../conf/
y arrancaríamos blaapps...
28. $ cd blaapps/bin
$ java -jar blaapps-kernel-launcher.jar ../conf/
Loading Libraries
/opt/blaapps/bin/../lib
[...]
Libraries Loaded
INFO [Blaapps-Core]: Starting Deployer...
INFO [Blaapps-Core]: Loading Module HiWorld
INFO [HiWorld]: Hello World!
INFO [Blaapps-Core]: Module HiWorld Loaded
INFO [Blaapps-Core]: Deployer Started
y arrancaríamos blaapps...
29. $ cd blaapps/bin
$ java -jar blaapps-kernel-launcher.jar ../conf/
Loading Libraries
/opt/blaapps/bin/../lib
[...]
Libraries Loaded
INFO [Blaapps-Core]: Starting Deployer...
INFO [Blaapps-Core]: Loading Module HiWorld
INFO [HiWorld]: Hello World!
INFO [Blaapps-Core]: Module HiWorld Loaded
INFO [Blaapps-Core]: Deployer Started
.quit
INFO [Blaapps-Core]: Deployer Shutdown...
INFO [Blaapps-Core]: Unloading Module
INFO [Blaapps-Core]: Module HiWorld Unloaded
INFO [Blaapps-Core]: Deployer Stopped
$
y arrancaríamos blaapps...
30. CORE ANNOTATIONS
Deployer
• @Module
• @Version
• @Dependency
Tres son las anotaciones necesarias para definir la metainformación de un módulo...
31. CORE ANNOTATIONS
Registros
Logger log = Logger.getLogger(“HiWorld”);
log.info(“Hola Mundo!”);
INFO [HiWorld]: Hola Mundo!
Se puede obtener un logger programáticamente...
32. CORE ANNOTATIONS
Registros
@Log
Logger log;
log.info(“Hola Mundo!”);
INFO [HiWorld]: Hola Mundo!
Pero Blaapps también puede crearlo por nosotros...
33. CORE ANNOTATIONS
Mensajería
@Inbox("evento")
private void onMessage(Message message)
@Inbox("evento")
private MessageStorage inbox;
Las colas de mensajes están formadas por dos partes: Los buzones de recepción y de envío.
Los buzones de recepción se pueden crear mediante la anotación @Inbox.
34. CORE ANNOTATIONS
Mensajería
MailBoxMBean mailbox =
! ! ! ! MainDeployerFactory.getServerMessageQueue();
Message message = new Message(this, true, atmnt1);
mailbox.sendMessage(“evento”, message);
Para enviar un mensaje al servidor, utilizamos el enviador del servidor...
35. CORE ANNOTATIONS
Configuración
@Conf
private Properties conf;
• Configuración por defecto
defaults.properties
• Configuración del usuario
carpeta "conf"
Blaapps permite cargar la configuración de un módulo con @Conf
@Conf junta la configuración por defecto de ese módulo con la definida por el usuario.
36. CORE ANNOTATIONS
Configuración
@ManagementServer
private MBeanServer server;
public PersistenceModule() {
! ObjectName persistenceName = new ObjectName(name);
! server.registerMBean(this, persistenceName);
}
• clase ManagementProxy
Blaapps inicia un MBeanServer para registrar elementos de gestión.
Todos los módulos publican una interfaz de gestión.
La clase ManagementProxy permite utilizar de manera fácil un MBean.
37. ¿CÓMO SE USA?
Blaapps Modules
Pasemos a ver los módulos de blaapps
38. MODULE ANNOTATIONS
Persistencia
• JPA Annotations
@PersistenceContext
@Entity
Primero vamos a hablar del !
@Module( módulo de persistencia.
name = "test",
Permite usar JPA en un módulo para acceder a una base de datos.
Acepta las anotaciones JPA. version = @Version(revision=5),
! ! ! !
! ! ! ! description = "Testing persistence",
39. Persistencia
@Module( !name = "test",
! ! ! ! version = @Version(revision=5),
! ! ! ! description = "Testing persistence",
! ! ! ! dependency = @Dependency(
! ! ! ! ! ! parentName = "Blaapps-Persistence",
! ! ! ! ! ! version = @Version(revision=5),
! ! ! ! ! ! comparator = Comparation.EQUAL,
! ! ! ! ! ! policy = DependencyPolicy.REQUIRED
! ! ! ! )
)
public class Module01 {
! @PersistenceContext
! private EntityManager em;
!
Para poder usar las clases del módulo de persistencia, tenemos que indicarlo como dependencia.
40. MODULE ANNOTATIONS
Objetos Remotos
• RMI Objects
@BStateless
@BRemote
El módulo de objetos remotos ofrece un mecanismo sencillo de publicación de clases RMI
41. Objetos Remotos
@Module(! name="test-remote-1",
! ! ! ! version=@Version(revision=5),
! ! ! ! description = "Testing Remote",
! ! ! ! dependency = @Dependency(
! ! ! ! ! ! ! parentName = "Blaapps-Remote",
! ! ! ! ! ! ! version = @Version(revision=5),
! ! ! ! ! ! ! comparator = Comparation.EQUAL,
! ! ! ! ! ! ! policy = DependencyPolicy.REQUIRED
! ! ! ! )
)
public class Module01 {
!
! ! ...
En el módulo en el que definamos los objetos RMI, tenemos que indicar Blaapps-remote como dependencia.
42. public interface DummyRemote Objetos Remotos
! ! ! ! ! ! ! ! extends Remote, Serializable {
! int getFive() throws RemoteException;
}
@BStateless(DummyRemote.class)
public class DummyRemoteObject implements DummyRemote {
! @Override
! public int getFive(){
! ! return 5;
! }!
}
En este módulo definimos una interfaz pública y una clase que la implementa.
La clase debe ser compatible con RMI.
Marcamos con @BStateless el interfaz público que implementa.
44. )
public class Module02 { Objetos Remotos
! @BRemote("test-remote-1")
! private DummyRemote dummy;
! @AfterDeployment
! public void testRemote(){
! ! if (dummy.getFive() == 5) {
! ! ! // Remote Module Works
! ! }
! }
Con la anotación @BRemote inyectamos una referencia a un objeto remoto
45. 3 RETOS
• Aislamiento
• Inyección de Dependencias
• Nuevas Instancias
Durante el desarrollo de blaapps el equipo de desarrollo se ha encontrado con 3 grandes retos.
El primero de ellos fue el asegurar el aislamiento entre módulos.
46. AISLAMIENTO
Problema
Usuarios Jabber
collections- collections-
commons-3.2.1.jar commons-2.1.1.jar
Si dos módulos utilizan distintas versiones de la misma librería o clase,
se tiene que asegurar el que cada módulo utilice su versión.
47. AISLAMIENTO
ClassLoaders
Bootstrap ClassLoader
Blaapps ClassLoader
lib lib
Usuarios Usuarios ClassLoader Jabber Jabber ClassLoader
Una forma de solucionarlo es encerrando a cada módulo en un hilo con su propio class loader.
48. AISLAMIENTO
ClassLoaders
Bootstrap ClassLoader
lib
Blaapps ClassLoader
lib lib
Usuarios Usuarios ClassLoader Jabber Jabber ClassLoader
Problema: ¿Qué pasa si blaapps utiliza una versión diferente de la librería?
49. AISLAMIENTO
ClassLoaders
Bootstrap ClassLoader
lib
Blaapps ClassLoader
lib lib
Usuarios Usuarios ClassLoader Jabber Jabber ClassLoader
Problema: ¿Qué pasa si blaapps utiliza una versión diferente de la librería?
50. AISLAMIENTO
ClassLoaders
Bootstrap ClassLoader
lib
Blaapps ClassLoader
lib lib
Usuarios Usuarios ClassLoader Jabber Jabber ClassLoader
Problema: ¿Qué pasa si blaapps utiliza una versión diferente de la librería?
51. AISLAMIENTO
ClassLoaders
Bootstrap ClassLoader
lib
Blaapps ClassLoader
lib lib
Usuarios Usuarios ClassLoader Jabber Jabber ClassLoader
Problema: ¿Qué pasa si blaapps utiliza una versión diferente de la librería?
52. AISLAMIENTO
IsolationClassLoader
Bootstrap ClassLoader
lib
Blaapps
IsolationClassLoader
lib lib
Usuarios Usuarios Jabber Jabber
IsolationClassLoader IsolationClassLoader
Solución: Creamos un classloader propio que invierta el orden en el que se buscan las clases.
53. AISLAMIENTO
IsolationClassLoader
Bootstrap ClassLoader
lib
Blaapps
IsolationClassLoader
lib lib
Usuarios Usuarios Jabber Jabber
IsolationClassLoader IsolationClassLoader
Solución: Creamos un classloader propio que invierta el orden en el que se buscan las clases.
54. AISLAMIENTO
IsolationClassLoader
Bootstrap ClassLoader
lib
Blaapps
IsolationClassLoader
lib lib
Usuarios Usuarios Jabber Jabber
IsolationClassLoader IsolationClassLoader
Solución: Creamos un classloader propio que invierta el orden en el que se buscan las clases.
55. AISLAMIENTO
IsolationClassLoader
Bootstrap ClassLoader
Blaapps
IsolationClassLoader
Usuarios Usuarios Usuarios
IsolationClassLoader
Permisos Permisos Permisos
IsolationClassLoader Usuarios
Además, si un módulo depende de otro, su classloader mantiene sus clases, y una copia de las clases de otro módulo.
Se tiene que forzar a los módulos a interactuar con sus interfaces públicos.
Problema: ¿Qué pasa si se tiene que usar una misma versión de una clase en dos módulos?
56. AISLAMIENTO
SharedClassLoader
Usuarios Usuarios Usuarios
IsolationClassLoader
Permisos Permisos Permisos
IsolationClassLoader Usuarios
Shared Classes
Usuarios Shared Clases Permisos Shared Clases
Solución: Se mantiene un espacio de clases compartidas, donde el desarrollador puede publicar clases.
Las clases compartidas sólo se cargan una vez en memoria.
57. AISLAMIENTO
SharedClassLoader
Usuarios Usuarios Usuarios
IsolationClassLoader
Permisos Permisos Permisos
IsolationClassLoader Usuarios
Shared Classes
Usuarios Shared Clases Permisos Shared Clases
Solución: Se mantiene un espacio de clases compartidas, donde el desarrollador puede publicar clases.
Las clases compartidas sólo se cargan una vez en memoria.
58. AISLAMIENTO
SharedClassLoader
Usuarios Usuarios Usuarios
IsolationClassLoader
Permisos Permisos Permisos
IsolationClassLoader Usuarios
Shared Classes
Usuarios Shared Clases Permisos Shared Clases
Solución: Se mantiene un espacio de clases compartidas, donde el desarrollador puede publicar clases.
Las clases compartidas sólo se cargan una vez en memoria.
59. INYECCIÓN DE
DEPENDENCIAS
EntityManager em = new EntityManager(?????);
• ¿Quién gestiona la configuración?
Si el desarrollador es el responsable de crear conexiones a la base de datos, también tiene que gestionar la
configuración.
Blaapps se encarga de crear conexiones a datos, pero, ¿cómo obtiene el desarrollador una?
Uno de los retos de Blaapps ha sido facilitar la creación de este tipo de objetos.
60. INYECCIÓN DE
DEPENDENCIAS
Inversión del control
EntityManager em = Persistence.getEM();
Una Factoría.
Problema: Genera código acoplado.
61. INYECCIÓN DE
DEPENDENCIAS
Inversión del control
EntityManager em;
public void setEm(EntityManager em) {
! this.em = em;
}
Inversión de control.
Problema: ¿Cómo sabe Blaapps que tiene que inyectar?
62. INYECCIÓN DE
DEPENDENCIAS
Programación Orientada a Aspectos
@PersistenceContext
EntityManager em;
Inyección de dependencias -> POA
Problema: ¿Cómo hacer un set a ese campo?
63. INYECCIÓN DE
DEPENDENCIAS
API Reflection
for (Field field : clazz.getDeclaredFields()) {
! if (
! ! field.isAnnotationPresent(PersistenceContext.class)!&&
! ! EntityManager.class.isAssignableFrom(field.getType())
! ) {
! ! field.setAccessible(true);
! ! field.set(obj, createEntityManager());
! }
}
Solución: API Reflection
64. NUEVAS INSTANCIAS
Notificando clases cargadas
loadClass()
Ejecución ClassLoader lib.jar
Blaapps necesita saber cuándo se cargan nuevas clases, y se crean nuevos objetos.
De esta manera, registra componentes e inyecta campos.
Blaapps sabe cuándo se carga una clase, se lo chiva el ClassLoader.
El ClassLoader manda un mensaje cada vez que se carga una clase.
65. NUEVAS INSTANCIAS
Notificando clases cargadas
loadClass()
Ejecución ClassLoader lib.jar
classLoaded()
MessageQueue
Blaapps necesita saber cuándo se cargan nuevas clases, y se crean nuevos objetos.
De esta manera, registra componentes e inyecta campos.
Blaapps sabe cuándo se carga una clase, se lo chiva el ClassLoader.
El ClassLoader manda un mensaje cada vez que se carga una clase.
66. NUEVAS INSTANCIAS
Notificando clases cargadas
loadClass()
Ejecución ClassLoader lib.jar
classLoaded()
MessageQueue
Deployer Deployer Deployer
Blaapps necesita saber cuándo se cargan nuevas clases, y se crean nuevos objetos.
De esta manera, registra componentes e inyecta campos.
Blaapps sabe cuándo se carga una clase, se lo chiva el ClassLoader.
El ClassLoader manda un mensaje cada vez que se carga una clase.
67. NUEVAS INSTANCIAS
Notificando nuevas instancias
?
Pero... ¿Cómo sabemos cuándo se crea una instancia de un Objeto?
No hay ninguna forma de saberlo.
Bueno, una sí, si nos lo dice el propio objeto...
68. NUEVAS INSTANCIAS
Javassist
loadClass()
Ejecución ClassLoader lib.jar
public class Class {
! public Class(){
inject()
! }
}
Javassist
Code
newInsance()
MessageQueue
En lugar de cargar en memoria la clase directamente, usaremos javassist.
Javassist es una librería que nos permite alterar los bytecodes de una clase.
Cada vez que se carga una clase, se añade un código al principio constructor.
Cuando se ejecuta, se lanza una notificación de que se ha creado la instancia.
69. NUEVAS INSTANCIAS
Javassist
loadClass()
Ejecución ClassLoader lib.jar
public class Class {
! public Class(){
inject()
Code
! }
}
Javassist
En lugar de cargar en memoria la clase directamente, usaremos javassist.
Javassist es una librería que nos permite alterar los bytecodes de una clase.
Cada vez que se carga una clase, se añade un código al principio constructor.
Cuando se ejecuta, se lanza una notificación de que se ha creado la instancia.
70. e !
Tim
m o Servidores de Aplicaciones
D e Q &A
Blaapps
Conclusiones
Demo
74. FUTURO
Estabilidad
•α → β → RC → GA
• Pruebas de unidad
• Librerías externas
Actualmente se considera que blaapps está en estado Alpha.
Se plantea pasar a Beta en la siguiente versión.
75. FUTURO
Funcionalidad
• Escritorio
• Web
• ¿Comunidad?
La funcionalidad futura pasará por ampliar horizontes.
Facilitar el desarrollo de todo tipo de aplicaciones. Servidor, web y Escritorio.
Pero será la comunidad, aquellos que usen y desarrollen blaapps, los que decidan por dónde irá el proyecto.
76. FUTURO
Comunidad
http://www.blaapps.org
La comunidad ya dispone de una página web donde colaborar.
77. BLAAPPS
• Modular
• Ligero
• Rápido
• Fácil de utilizar
Blaapps es ligero y flexible. Y además utiliza tecnologías estándar.
Migrar de Blaapps a un servidor mayor no es problema.
Modificar Blapps para que escale no es problema.
En definitiva, es ideal para proyectos que empiezan. Crea algo muy rápido, y luego hazlo crecer.
78. BLAAPPS
• Modular
• Ligero
• Rápido
STARTUPS
• Fácil de utilizar
Blaapps es ligero y flexible. Y además utiliza tecnologías estándar.
Migrar de Blaapps a un servidor mayor no es problema.
Modificar Blapps para que escale no es problema.
En definitiva, es ideal para proyectos que empiezan. Crea algo muy rápido, y luego hazlo crecer.