jueves
feb142013
Disponible Spring Data GA 1.0
Spring Data es un proyecto de SpringSource cuyo propósito es facilitar el uso de bases de datos no relacionales, de frameworks map-reduce, y de servicios de datos albergados en "la nube". Se trata de un proyecto paraguas que contiene muchos otros proyectos que permiten trabajar con una base de datos específica.
Ayer Spring Source anunció la disponibilidad de la primera versión estable, Spring Data GA 1.0, de este proyecto.
Entre las fuentes de datos aportadas se encuentran MongoDB, GemFire, Neo4j, HBase, Redis, Hadoop, servicios REST en general, JPA y otros. Aquí os dejo una tabla con todas las fuentes de datos soportadas por spring Data:
SPRING DATA PROJECTS:
Category | Sub-project | |
Relational Databases | JPA | Spring Data JPA - Simplifies the development of creating a JPA-based data access layer |
JDBC Extensions | Support for Oracle RAC, Advanced Queuing, and Advanced datatypes. Support for using QueryDSL with JdbcTemplate. | |
Big Data | Apache Hadoop | The Apache Hadoop project is an open-source implementation of frameworks for reliable, scalable, distributed computing and data storage. |
Data-Grid | GemFire | VMware vFabric GemFire is a distributed data management platform providing dynamic scalability, high performance, and database-like persistence. It blends advanced techniques like replication, partitioning, data-aware routing, and continuous querying. |
HTTP | REST | Spring Data REST - Perform CRUD operations of your persistence model using HTTP and Spring Data Repositories. |
Key Value Stores | Redis | Redis is an open source, advanced key-value store. |
Document Stores | MongoDB | MongoDB is a scalable, high-performance, open source, document-oriented database. |
Graph Databases | Neo4j | Neo4j is a graph database, a fully transactional database that stores data structured as graphs. |
Column Stores | HBase | Apache HBase is an open-source, distributed, versioned, column-oriented store modeled after Google' Bigtable |
Common Infrastructure | Commons | Provides shared infrastructure for use across various data access projects. General support for cross-database persistence is located here |
Grails Mapping | Provides a database unified object mapping framework that is portable across different databases for Grails. |
Reader Comments (25)
Spring es un dinosaurio que va a reventar antes de que caiga un meteorito.
A mi me parece una gran noticia este proyecto por parte de spring, Juan, podrias comentar pq spring es un dinosaurio? hay alternativas reales a spring por ahí? que hagan lo mismo o mejor y que esté en producción ? Lo pregunto para saber algo mas, no por trollear, me interesa tu opinion. Gracias
No sé juan si lo usaras mucho o no pero facilita muuuucho las cosas. Nosotros usamos Spring Framework, Spring Data (mongoDb, Redis, JPA), Spring Flex, Spring Security y nos va muy bien.
Spring es lo que está salvando Java desde hace años. Yo estoy usando varias partes de Spring Data y me parece una gran opción.
todo el tiempo ahorrado se pierde configurando sus archivos de configuraciones en realidad no ganas nada incluso es mejor no usarlo en absoluto
todo el resto de frameworks que realmente son productivos simplemente no configuras nada solo creas pojos de toda la vida y sigues las convenciones que en el 90% de las veces son correctas y coherentes y el 10% de las veces sobrescribes la configuración usando anotaciones
Con el resto de los frameworks lo único que haces es escribir código que casi siempre funciona (90%) directamente sin realizar ningún esfuerzo solo basta con agregar las librerías en el classPath no es necesario instalar nada mas ni bajarse todos los plugins es solamente una simple y común librería
Con el resto de los frameworks todo es tipado fuerte no necesitas nada para que funcione correcto si cometes un error el compilador te lo corrige así de simple
Es decir tienes todas las ventajas y funcionalidades de spring pero sin sus problemas
Con spring escribes código "puro sin cosas raras y como te gusta" pero jamas funciona luego tienes que escribir exactamente lo mismo en un archivo de configuración repitiendo lo mismo que programaste (usando copy and paste) si escribes mal el archivo de configuración simplemente no te das cuenta a menos que descarges 15 mil plugins el compilador no te avisa que tiene problemas
Yo cuando quiero hacer un refactoring simplemente lo realizo así de simple no me gusta como se llama una clase simplemente lo cambio pero con spring los nombres de las clases están copiados en varios archivos los cuales están repetidos en varias partes dentro del archivo simplemente no puedes modificar nada por que toda la aplicación deja de funcionar
lo mismo pasa con la estructura de paquetes simplemente no puedes cambiarla
No se si esta tanto como que spring esté salvando java, pero si me parece una magnifica forma de construir aplicaciones robustas, llevo usando como 6 años este fw y ahora sale de forma natural el concepto de inyeccion de dependencias, aop, spring security cumple perfectamente con su cometido, spring webflow lo mismo, spring mvc es una aplicación del patron mvc, uno mas, vale pero esta bastante bien. Spring data es la nueva aportacion y parece una solucion super elegante de tener tus conectores nosql con el patron singleton, que mas se puede pedir?
Luis Ernesto, por decir cosas similares hace años algunos me tiraban a la hoguera :)
Echad un vistazo a este código de Struts:
< forward name="bien" path="/hola.jsp" / >
< forward name="error" path="/error_hola.jsp" / >
< / action >
primerstruts.saludo.SaludoAction es una clase definida por nosotros ¿verdad? ¿cual es el requisito dado por Struts en los constructores de SaludoAction para la creación de este objeto?
Respuesta: ninguno, un constructor vacío vale.
Pregunta: ¿como obtenemos entonces las dependencias de SaludoAction por ejemplo para acceder a una base de datos?
Respuesta:
1) Con un método public static DataSource getDataSource() {...} directa o indirectamente llamado en SaludoAction y de forma similar los DAOs (si estos son singletons) etc. Infierno de métodos estáticos.
2) El mismo típo de código pero vía Spring al menos el primer bean (singleton), los demás singleton se obtienen ya inyectados, el código de bindings de las implementaciones concretas se realiza via XML
3) Inyectado el bean que se quiera directamente en SaludoAction a través de un plugin-in para Struts, sistema de plug-ins definido a partir de Struts 1.1
http://static.springsource.org/spring/docs/3.0.0.M3/reference/html/ch19s04.html
Obviando el caso 3 en donde el propio Struts ya ofrece una extensión ¿el caso 2 parece más elegante que el caso 1 verdad?
Pero ¿cual es la raíz del problema?
En mi opinión el problema raíz ES DE STRUTS Y SU ABSURDA AUSENCIA DE ALGUN TIPO DE OBJETO DE CONTEXTO CONFIGURABLE POR EL PROGRAMADOR Y SUMINISTRADO POR EL PROPIO Struts
A vale que entonces SaludoAction ya no sería un POJO ¿pero desde cuando un objeto es un POJO cuando tiene métodos impuestos por Struts y claramente dependientes de Struts para ejecutar la acción web?
Si Struts hubiera tenido desde el principio un objeto contexto global preferentemente definido por el usuario a través de herencia... otro gallo nos hubiera cantado.
En Android se define un objeto aplicación en un XML definido por el programador heredado de Application, todos los objetos de vista definidos por el usuario y declarados en los XML de layout de Android reciben este objeto Application.
¿Métodos estáticos para obtener singletons? 0 (si quieres claro)
¿Uso de inyección de dependencias en Android? por parte de Android 0, algo hay de uso marginal y escasísimo valor.
El problema es que Google no metió las narices en la era Struts, si hubiera sido así otro gallo nos hubiera cantado.
Luis Ernesto, por decir cosas similares hace años algunos me tiraban a la hoguera :)
Echad un vistazo a este código de Struts:
[action path="/saludo" type="primerstruts.saludo.SaludoAction"]
[forward name="bien" path="/hola.jsp" /]
[forward name="error" path="/error_hola.jsp" /]
[/action]
primerstruts.saludo.SaludoAction es una clase definida por nosotros ¿verdad? ¿cual es el requisito dado por Struts en los constructores de SaludoAction para la creación de este objeto?
Respuesta: ninguno, un constructor vacío vale.
Pregunta: ¿como obtenemos entonces las dependencias de SaludoAction por ejemplo para acceder a una base de datos?
Respuesta:
1) Con un método public static DataSource getDataSource() {...} directa o indirectamente llamado en SaludoAction y de forma similar los DAOs (si estos son singletons) etc. Infierno de métodos estáticos.
2) El mismo típo de código pero vía Spring al menos el primer bean (singleton), los demás singleton se obtienen ya inyectados, el código de bindings de las implementaciones concretas se realiza via XML
3) Inyectado el bean que se quiera directamente en SaludoAction a través de un plugin-in para Struts, sistema de plug-ins definido a partir de Struts 1.1
http://static.springsource.org/spring/docs/3.0.0.M3/reference/html/ch19s04.html
Obviando el caso 3 en donde el propio Struts ya ofrece una extensión ¿el caso 2 parece más elegante que el caso 1 verdad?
Pero ¿cual es la raíz del problema?
En mi opinión el problema raíz ES DE STRUTS Y SU ABSURDA AUSENCIA DE ALGUN TIPO DE OBJETO DE CONTEXTO CONFIGURABLE POR EL PROGRAMADOR Y SUMINISTRADO POR EL PROPIO Struts
A vale que entonces SaludoAction ya no sería un POJO ¿pero desde cuando un objeto es un POJO cuando tiene métodos impuestos por Struts y claramente dependientes de Struts para ejecutar la acción web?
Si Struts hubiera tenido desde el principio un objeto contexto global preferentemente definido por el usuario a través de herencia... otro gallo nos hubiera cantado.
El problema es que otros MUCHOS frameworks web no han hecho más que imitar la cagada de Struts. No nos engañemos el IoC Spring en cuanto a singletons no es más que una forma sofisticada de definir y de llamar a static MiClase getInstanciaDeMiClase() { ... } con el precio de que los bindings de los objetos concretos devueltos se hace via XMLs que "sospechosamente" se parecen muchísimo a código Java pero ... en XML.
En Android se define un objeto/clase aplicación en un XML definido por el programador heredado de Application, todos los objetos de vista definidos por el usuario y declarados en los XML de layout de Android reciben este objeto Application. Y se acabó, en dicha clase derivada de Application el programador define todos los singletons que le de gana y su configuración si se quiere se puede obtener via XMLs de propiedades gestionados por Android.
¿Métodos estáticos para obtener singletons? 0 (si quieres claro)
¿Uso de inyección de dependencias en Android? por parte de Android 0, algunos usan algo pero con popularidad muy escasa y escasíiiiisimo valor aportado.
https://github.com/roboguice/roboguice/wiki
No, de Guice no hay ni rastro que yo sepa en el código fuente de Android.
El problema es que Google no metió las narices en la era web, si hubiera sido así otro gallo nos hubiera cantado.
@jmarranz El argumento de que inyección de dependencias = toneladas del XMLs ya hace mucho que no es válido :)
Yo uso DI y no tengo ni un XML. Y la poca configuración de bindings que hago me ocupa 10 lineas de código.
Otra cosa es que la gente abuse de ciertas cosas como pollos sin cabeza y que lo usen indebidamente, pero eso ya es otra discusión :)
@jerolba supongo que hablamos de Java config de Spring ¿no?
Aclaración: cuando hablo de "inyección de dependencias" hablo de "inyección automática de dependencias", porque inyección manual de dependencias hago todos los días a todas horas.
Si el, Java config de Spring (que no la he llegado a usar) o de los Modules de Guice (que es lo que uso ahora)
Seguro que te simplificaría bastante esa inyección manual que haces ahora, y con las mismas garantías :)
Psss puede ser... pero no creo.
La "vida" me ha enseñado que la gestión de dependencias es uno de los aspectos más valiosos de tu código y no lo delego en nadie salvo que me de muchísimo valor, y no, un 5% de reducción de código, una viralidad inducida de singletons, objetos configurados via set en vez de via constructor y otras rigideces no son precisamente ventajas.
Y en el ámbito del desktop (incluyo Android e ItsNat) en donde me he movido y me muevo, la gestión de singletons son una mera anécdota. Remarco lo de los singletons porque es donde la gestión automática de dependencias ha sido extensivamente usada. Para un paranoico de la gestión y del control del código no sólo no me añade control sino que me lo quita.
@jmarranz Que tu configuración manual de dependencias alcance un 5% de tu código me parece una burrada. Si es así, necesitas un Guice con urgencia! :)
Cualquier cosa mal usada, por muy buena que sea su teoría, acaba mal. En este caso, nadie te obliga a usar Singletons, ni a configurar por setters. Que se pueda hacer no implica que te obligue a hacerlo o sea la única manera de hacerlo, ni descalifica a la heramienta.
Tú directamente no lo hagas, como hago yo :)
No Jero, con lo del 5% me refiero "a ahorro de código respecto a una gestión manual de depedencias". El valor es un dato que me he inventado yo, puedo llegar a aceptar 10% pero no más, no perdamos la perspectiva, la inyección **automática** de dependencias es eso, automática, es decir "lo hago yo no tu".
Respecto al tema de los singletons, el 99% del uso de un DI automático es para la inyección de singletons, fuera de los singletons el tema del DI automático se pone tan feo que por eso no vas a ver gran cosa en ámbitos tipo GUI. Es verdad que algo de utilidad tiene el scope prototipo.
Jmaraz es enserio.Todos los frameworks no usan singleton por defecto spring y guice y todo el resto crean una nueva instancia cada ves que la necesitan todo lo opuesto singleton
no hay tal cosa como una proliferación de singletons cada ves que quieras uno lo configuras.En pocas palabras la opción por defecto es crear nuevas instancias no singletons
lo normal es tener una sarta de personas que copian y pegan código sin pensar y no se dan cuenta de las opciones ni los errores que comenten.En spring es posible inyectar todas las decencias por el constructor.El echo que casi nadie lo use es por su poco conocimiento y tolerancia al código basura .En guice la inyección por el constructor es la opción por defecto
Yo también considero la gestión de dependencia como una cosa importante. La herramienta no tiene absolutamente nada que ver con como gestionas las dependencias .Puedes gestionar las dependencias como se te de la gana y lo puedes hacer a mano (inyectando por el constructor en el método main) o con framework y va a ser la misma estructura.
Con el framework o sin el, cualquiera que se preocupe en como gestiona sus dependencias va a hacer exactamente lo mismo. El contenido va a ser el mismo solo que la forma como lo hagas va a variar
Luis The singleton scope is the default scope in Spring"
"no hay tal cosa como una proliferación de singletons"
Para poder inyectar un bean necesitas que la clase contenedora sea a su vez "managed" por el framework, en el 99% por ciento de las ocasiones acabará siendo esa clase contenedora un singleton gestionado a su vez por el motor DI.
Por ponerlo de forma clara:
class MyClassWithAnyKindOfLifeCycle { @Inject MySingletonClass obj; }
¿Qué hago para que pueda inyectar MySingletonClass? añadirlo a las clases gestionadas...
Un sistema DI basado en byte weaving aliviaría mucho y es la DI automática no intrusiva que verdaderamente me gusta ...
"Con el framework o sin el, cualquiera que se preocupe en como gestiona sus dependencias va a hacer exactamente lo mismo"
Exacto.
Quizás defendiendo que "hay otra forma de hacer las cosas" no oiremos tonterías de algunos que han dejado Java "porque es demasiado complicado porque tiene montones de artefactos y capas".
@jmarranz No sé de donde te sacas que DI automático = singletons
Yo hago DI automático y los singletons que tengo son casos contados (los estrictamente necesarios). Y nunca he tenido la sensación de que por hacerlo se me vaya a poner feo ni a perder el control de mis objetos...
Aclaración para Jero: tienes un singleton de la clase MySingletonClass gestionado por un motor DI, ¿como obtienes una referencia de dicho objeto?
Dos formas:
1) Via lookup del bean, por ejemplo con Spring via ApplicationContext.getBean()
2) Inyectando en el objeto que lo va a usar, lo normal es que sea en un atributo
¿A que es más "cool" la opción 2? ¿a que lo fácil es convertir la clase que usa el singleton a su vez en otro singleton pues total esa clase la vamos a usar?
Es posible que viva en otra realidad, si es así por favor abrirme los ojos.
¿no es cierto que la inmensa mayoría de los objetos Java que sirven la mayoría de las aplicaciones web que usan DI automática son singleton? (nota: he oído mil veces que usar new no es "cool" y que es una mala práctica)
¿incluso con aplicaciones que hacen un notable uso de la sesión web y que por tanto tienen una gestión de estado significativa?
De acuerdo con ésto, ¿no son dichas aplicaciones meros repartidores de mensajes (llamadas a métodos) entre singletons?
¿donde queda la herencia y el polimorfismo si la inmensa mayoría de las decisiones de control en ejecución se toman sin crear objetos (cuya implementación sería elegida como la adecuada al contexto) y por tanto practicamente todas las decisiones se toman a través de ifs dentro de dichos singleton?
¿se entiende por qué en desktop o en desarrollo móvil o en UI web Single Page Interface (por ejemplo via GWT o JavaScript o Vaadin) la DI automática es prácticamente una rareza porque programar a base de singletons si que es ya prácticamente imposible?
¿os suena lo de la campaña anti-if?
¿donde quedan 30 años de POO?
Una cosa que se puede hacer con guice (ignoro si se puede hacer con spring), es la inyección de dependencias no sólo en objetos del digamos "wiring inicial" (los singleton que critica jmarranz) sino que también se pueden añadir dependencias mediante los FactoryProviders, de modo que podrías tener una clase donde algunas dependencias se las suministra el programador y otras el framework de DI (Por ejemplo, estoy leyendo Alumnos de una bd e instanciado una por cada row, con los datos de la bd que yo suministro y el framework de DI suministra el resto de dependencias). Cuando usaba guice esta característica me era muy útil, aunque quizá un poco confusa de entender cuando alguien se encontraba con esto sin conocer guice previamente.
Ahora estoy haciendo inyección de dependencias a mano (con new vamos) porque en groovy existe por defecto un constructor que recibe un mapa y me permite hacer algo como.
def myDependency = new MyConcreteDependency()
def otherObject = new OtherObject(dependency: myDependency, otherDependency: ...)
Esto me resulta más semantico y además no me obliga a modificar los constructores cada vez que tengo que añadir una nueva dependencia. El duck typing también ayuda a simplificar porque ya no necesitas declarar interfaces para depender de abstracciones. Vamos que en un lenguaje dinamico no veo tanta necesidad de usar un framework de DI, no aporta gran cosa, en java si que usaba guice y bueno, algo más comodo que hacer los new's a mano si resultaba, pero no hay mucha diferencia en el fondo si sabes lo que haces.
Se me olvidaba el origen del post jeje: Nosotros estamos empezando a usar mongo, y lo estamos haciendo a través de Gmongo (una capa fina sobre el driver original de java para hacerlo más "groovy") y sinceramente, no veo que spring data me aporte absolutamente nada.
Y por dios, si alguien usa un NoSql schema-less como mongo y "mapea POJO's" debería hacerselo mirar.
@jmarranz Si ese objeto tiene ese único atributo, técnicamente te daría igual que fuera un singleton, pero yo personalmente lo dejaría como una clase normal, donde da la casualidad de que uno de sus atributos es un singleton. Pero como no tiene por qué saberlo, mejor dejarlo normal, no vaya a ser que un día deje de ser un singleton y la liemos :)
Los tiempos en los que el controlador de una aplicación web era un singleton hace tiempo que pasaron. La culpa es de la especificación de Servlets que pide que sea un singleton y todo los frameworks que se hicieron sobre ellos mantenían ese comportamiento (cuantos bugs he visto por su culpa y cuanto mal ha hecho!!). Con eso, como tu dices, todas las capas inferiores tenían que recurrir a singletons una tras otra.
Pero ya incluso en Struts 2 cada action es una instancia nueva, por lo que no te fuerza a reutilizar siempre la misma instancia, con sus dependencias ya cargadas desde el principio.
@Alfredo, Si, el assisted inject de Guice está muy bien, porque puedes mezclar las dos comportamientos: asignar valores tuyos en tiempo de ejecución, y que inyecte los atributos que hayas configurado. El único pero que tiene es que es un poco verboso teniendo que crear una clase factoría, pero para ciertas cosas lo pago con gusto :)
Alfredo, lo del constructor con parámetros por nombre, ¿solo ayuda con la expresividad no?,no te ahorra el trabajo de tener que hacer los news, y no puedes configurar desde fuera las implementaciones de ciertas interfaces, no? (como lo harías en guice)
Otra pregunta: ¿En groovy es obligatorio pasarle todos los atributos al constructor? O simplemente te pone a null los atributos que no nombres en el new?
Si son opcionales, ahí veo un problema, ya que si mañana añades una dependencia en tu clase, tendrás que repasar tu código buscando donde lo instancias para completarlo. Ya sé que con tú con tus test unitarios te saltarán los errores, pero no será hasta que los ejecutes, y además sería un nullpointerexception en una linea que no tiene que ver con el constructor...
Por último, Alfredo, yo si veo un caso de uso en donde uses Mongo con Pojos y schema less, porque lo he usado en otra "BD nosql". Es cuando tu documento, por composición, y de forma recursiva, puede tener multiples tipos de clases con polimorfismo. En vez de implementar toda esa herencia en el modelo relacional, con el infierno de tablas que te pueden salir, las metes directamente como un documento. De esta forma te sale un tipo de colección en vez de decenas de tablas.
"¿solo ayuda con la expresividad no?,no te ahorra el trabajo de tener que hacer los news, y no puedes configurar desde fuera las implementaciones de ciertas interfaces, no?"
Claro te ahorras escribir el constructor tb. No se si te entiendo con lo de configurar desde fuera. Cuando hago los "news" decido que implementaciones poner en cada sitio, al final en mi aplicación tengo un trocito de código (una factoria por ejemplo) que es la que hace estos "news" y monta todo el wiring inicial, en realidad es casi lo mismo que tener un modulo de guice configurando un injector, la diferencia es que usas "new" y caracteristicas propias del lenguaje en lugar de una librerías para montar tu factoria (que el injector no es más que eso en el fondo).
Los parametros del constructor son opcionales claro, como tu dices si se te olvida alguno nullPointer al canto. Pero en guice no es muy diferente, si se te olvida poner en el modulo alguna dependencia que luego necesita una clase a instanciar en lugar de un nullpointer tienes un error de guice diciendo que te falta tal dependencia, es mejor que un nullpointer eso seguro, pero no deja de ser un error en tiempo de ejecución.
El tema de los pojos con schema-less es que en cierta medida estas haciendo que tu sistema siga siendo igual de rigido, no lo es en la persistencia pero si lo es en tu código. Claro que de nuevo un lenguaje dinamico aqui simplifica una barbaridad jeje.
@Alfredo, aparte de ganar expresividad, lo demás, lo de la factoría sigue siendo igual lo hagas en groovy o lo hagas en java. Es decir que el lenguaje no te ayuda a simplificar esa construcción de las factorías.
Jeje, en lo del schema less de los pojos, te digo lo de siempre: yo lo quiero rígido :)
Si le meto un atributo a mi pojo, la persistencia se lo come del tirón sin tocar nada (por ser schema less), y a nivel de código tengo la seguridad de que el atributo existe, compilo bien y que manejo el tipado correcto.
Otra cosa es que tú quieras hacer uso de ciertas funcionalidades del lenguaje dinámico sobre tus clases de dominio, pero eso ya no está relacionado con la persistencia, sino con cómo implementas tu lógica de negocio.
Estoy con Jero en lo de la persistencia, siempre hay esquema, mas o menos rigido o llamalo implicito en el codigo, yo por ejemplo en Android no uso BD y guardo JSON que me permite cargar datos antiguos flexiblemente de versiones antiguas, y lo convierto al modelo de datos Java convencional mas actual, sin duda el no tener un esquema rigido en persistencia es genial en este caso, eso no impide un modelo convencional aunque ciertamente ya no hay simetria exacta.
"Es decir que el lenguaje no te ayuda a simplificar esa construcción de las factorías."
En cierto modo si por el tema de los constructores, pero la factoría la tienes que escribir a mano. Quizá la ventaja principal que le veo a este enfoque es la simplicidad, no tengo que usar ningún framework y me es muy facil explicarle a la gente como funcionan las cosas. De todos modos, esto lo estoy probando en un desarrollo nuevo, según vaya creciendo quizas se me compliquen mucho las dependencias y sea un desastre no se jeje. Otra cosa buena es que el código de construcción es eso "código" y se puede refactorizar para irlo simplificando si se desmadra mucho.
Lo del schema-less va en gustos supongo, tiene más que ver con la forma en la construyas tu aplicación en eso estoy de acuerdo