SD Card Recovery
El problema que resolvemos hoy es algo que nos puede pasar a cualquiera, esta tarjeta SD de la cámara de fotos del movil que de repente ya no puede leerse y el sistema operativo nos dice si queremos formatearla.
La solución esta herramienta gratuita y muy fácil de usar: PhotoRec
A pesar de que el aspecto al ejectuarlo es en modo consola, es muy fácil e intuitiva de usar ya que se maneja con las fechas del teclado y el intro.
1 - Ejecutamos el archivo: photorec_win.exe(yo tengo windows) con la tarjeta SD ya introducida en el ordenador.
2 - Nos aparecerán todas las unidades de disco disponibles y seleccionamos la de la tarjeta SD.
3 - Una vez seleccinado seleccionamos el tipo de formateo que tiene la tarjeta, en Windows los normal es FAT32.
4 - Selecionamos el directorio donde se copiarán los archivos recuperados.
5 - Pulsamos en la opción Search y pasado un tiempo tendremos los archivos recuperados.
Referencia:
SD 6 data recovery tools for SD cards, USB drives and more
Translate
miércoles, 19 de diciembre de 2012
lunes, 3 de diciembre de 2012
Herramientas útles: Plumbr memory leaks detector
Lo primero que hay que decir es que es una herramienta de pago y no todo el mundo puede permitírsela pero la manera que tiene de descubrir los memory leaks tiene buena pinta.
Puede ser una opción interesante para una nuestra aplicación si existen muchos problemas y nos vemos desesperados.
http://plumbr.eu/getting-started/1-take-the-tour
Puede ser una opción interesante para una nuestra aplicación si existen muchos problemas y nos vemos desesperados.
http://plumbr.eu/getting-started/1-take-the-tour
miércoles, 28 de noviembre de 2012
Jenkins: Arrancar Jenkins fácilmente y en otro puerto diferente al 8080
Para los que usamos integración continua en nuestros proyectos una de las herramientas claves es JENKINS que es el servidor de integración continua.
Este puede instalarse en un máquina dedicada, pero para hacer pruebas también puede ejecutarse directamente desde el war que descarga de la web.
Para ello lo más fácil es poner la siguiente instruccion en una consola de comandos y desde el directorio donde esta el WAR.
java -jar jenkins.war --httpPort=8089
Y en tu navegador pones la siguiente URL y ya accedes a Jenkins:
http://localhost:8089/
Este puede instalarse en un máquina dedicada, pero para hacer pruebas también puede ejecutarse directamente desde el war que descarga de la web.
Para ello lo más fácil es poner la siguiente instruccion en una consola de comandos y desde el directorio donde esta el WAR.
java -jar jenkins.war --httpPort=8089
Y en tu navegador pones la siguiente URL y ya accedes a Jenkins:
http://localhost:8089/
viernes, 23 de noviembre de 2012
Maven: Recuperar la última versión de una dependencia
title: Get de LATEST versión of a dependency
En nuestro proyecto tenemos 5 proyectos puros Java que son APis, que son utilizadas por otros 5 proyectos Java/Flex.
Los proyectos Api están cambiando constantemente de versión, por este motivo en lo archivos pom.xml quiero recuperar siempre la última versión de cualquiera de esa API.
Para conseguirlo lo más fácil es porner en el apartado de versión de la dependencia:
<version>LATEST</version>
Referencias:
http://stackoverflow.com/questions/30571/how-do-i-tell-maven-to-use-the-latest-version-of-a-dependency
En nuestro proyecto tenemos 5 proyectos puros Java que son APis, que son utilizadas por otros 5 proyectos Java/Flex.
Los proyectos Api están cambiando constantemente de versión, por este motivo en lo archivos pom.xml quiero recuperar siempre la última versión de cualquiera de esa API.
Para conseguirlo lo más fácil es porner en el apartado de versión de la dependencia:
<version>LATEST</version>
<dependencies> <dependency> <groupId>log4j</groupId> <artifactId>log4j</artifactId> <version>LATEST</version> </dependency> </dependencies>
Referencias:
http://stackoverflow.com/questions/30571/how-do-i-tell-maven-to-use-the-latest-version-of-a-dependency
lunes, 19 de noviembre de 2012
Java: Formato de Fecha en español
Este problema me ha surgido porque tengo que formatear la fecha al siguiente formato "11 de noviembre de 2012" pero con el formato strandar lo que nos devuelve es "11 de November de 2012".
Para conseguir esto lo que hay que hacer es poner el Locale al SimpleDateFormat que se encarga de formatear de la fecha.
Referencia:
SimpleDateFormat en Java 7
Para conseguir esto lo que hay que hacer es poner el Locale al SimpleDateFormat que se encarga de formatear de la fecha.
SimpleDateFormat format = new SimpleDateFormat("dd 'de' MMMM 'de' yyyy",new Locale("es"));
Referencia:
SimpleDateFormat en Java 7
miércoles, 14 de noviembre de 2012
SpringFlex: getRealPah en un @RemotingDestination
title: getRealPath in a @RemotingDestination
En las versiones previas de las librerías de Spring Flex la manera de acceder al realPath era la siguiente:
FlexContext.getServletContext().getRealPath("")
Esto nos da acceso a la ruta física del servidor donde está alojada nuestra aplicación, pero el problema es que en las nuevas versiones (como la 1.5.2 Release) al intentar recuerar el ServletContext nos devueve nullPointerException.
La solución para resolver esto y volver a recuperare el valor es la siguiente:
FlexContext.getHttpRequest().getRealPath("");
El métdo está deprecado pero para esta versión sigue funcionando sin problemas.
En las versiones previas de las librerías de Spring Flex la manera de acceder al realPath era la siguiente:
FlexContext.getServletContext().getRealPath("")
Esto nos da acceso a la ruta física del servidor donde está alojada nuestra aplicación, pero el problema es que en las nuevas versiones (como la 1.5.2 Release) al intentar recuerar el ServletContext nos devueve nullPointerException.
La solución para resolver esto y volver a recuperare el valor es la siguiente:
FlexContext.getHttpRequest().getRealPath("");
El métdo está deprecado pero para esta versión sigue funcionando sin problemas.
jueves, 8 de noviembre de 2012
Tomcat: Arrancar Tomcat con parámetros
Una vez visto como se arranca el tomcat desde linea de comandos en la misma ventana de comandos de windows en unos de los artículos anteriores.
Ahora vamos ver como añadir parámetros desde la línes de comandos de tomcat, para hacerlo utilizamos lo que tenemos añadir es la variable de entorno JAVA_OPTS y podemos añadir todos los parámetros que necesitemos.
Ahora vamos ver como añadir parámetros desde la línes de comandos de tomcat, para hacerlo utilizamos lo que tenemos añadir es la variable de entorno JAVA_OPTS y podemos añadir todos los parámetros que necesitemos.
set JAVA_HOME=D:\Java\jdk1.7.0_02 set JAVA_OPTS=-Xms800m -Xmx800m -XX:MaxPermSize=256m catalina run
viernes, 2 de noviembre de 2012
Subida de archivos con Flash en MacOS : TypeError: Error #1009
TypeError: Error #1009: Cannot access a property or method of a null object reference Uploading file.
Este error se produce cuando intentamos subir un archivo con el sistema operativo Mac a través del Flash Player (actualmente la versión 11.4).
El problema consiste en que en el objeto FileReference que se encarga de identificar el archivo que subimos, si accedemos a la propiedad "type" esta llega con valor null y si la utilizamos nos dará el error antes tipificado. TypeError: Error #1009
Para solucionarlo lo mejor es recuperar la extensión del archivo del nombre del fichero del FileReference, con las propiedad "name".
Este error se produce cuando intentamos subir un archivo con el sistema operativo Mac a través del Flash Player (actualmente la versión 11.4).
El problema consiste en que en el objeto FileReference que se encarga de identificar el archivo que subimos, si accedemos a la propiedad "type" esta llega con valor null y si la utilizamos nos dará el error antes tipificado. TypeError: Error #1009
var fileReference:FileReference fileReference.type //NULL
Para solucionarlo lo mejor es recuperar la extensión del archivo del nombre del fichero del FileReference, con las propiedad "name".
var fileReference:FileReference fileReference.name //file.txt
viernes, 19 de octubre de 2012
Flex Spark: z-index en flex
El problema en que me visto esta semana es que teniendo una pantalla que ya estaba creada he tenido que poder una capa encima de otra ya existente bajo determinadas condiciones.
En la pantalla aparece una lista con distintos objetos cargadas y al pulsar un botón debía de aparecer otra lista encima de la ya existente.
Si la pantalla no estuviera ya hecha lo mejor sería utilizar un estado pero creo que para este caso lo mejor es crear la segunda lista y ponerla por encima de la ya existente, haciéndola visible o invisible según me convenga.
Para esto puedo usar la propiedad depth que tiene todo Spark container, la profundida por defecto es 0 y si queremos que algún container de nuestro mxml este por encima de otro debemos de pone está propiedad depth con valores mayores a 0.
referencias:
documentación de adobe
En la pantalla aparece una lista con distintos objetos cargadas y al pulsar un botón debía de aparecer otra lista encima de la ya existente.
Si la pantalla no estuviera ya hecha lo mejor sería utilizar un estado pero creo que para este caso lo mejor es crear la segunda lista y ponerla por encima de la ya existente, haciéndola visible o invisible según me convenga.
Para esto puedo usar la propiedad depth que tiene todo Spark container, la profundida por defecto es 0 y si queremos que algún container de nuestro mxml este por encima de otro debemos de pone está propiedad depth con valores mayores a 0.
-- <s:group depth="1" height="570" top="{50" width="100%"> .... .... </s:group> --
referencias:
documentación de adobe
miércoles, 10 de octubre de 2012
Tomcat: Arrancar tomcat en la misma ventana de comandos en Windows
Start tomcat in the same command window
Cuando intentamos configurar rápidamente un tomcat 6 o 7 el primer problema que con encuentro es que al lazar el comando startup o catalina start todo las trazas e información me aparecen en una ventana de comandos nueva.
Eso no estaría nada mal si esa ventana no se cerrara al terminar la ejecución o cuando ocurre un problema en el arranque inicial del tomcat.
Para que todo arranque dentro de la misma ventana de comandos debemos de arrancar tomcat con la siguiente línea de comandos:
catalina run
referencias:
http://stackoverflow.com/questions/6862696/redirect-tomcat-7-console-log-output-to-a-file-windows
Cuando intentamos configurar rápidamente un tomcat 6 o 7 el primer problema que con encuentro es que al lazar el comando startup o catalina start todo las trazas e información me aparecen en una ventana de comandos nueva.
Eso no estaría nada mal si esa ventana no se cerrara al terminar la ejecución o cuando ocurre un problema en el arranque inicial del tomcat.
Para que todo arranque dentro de la misma ventana de comandos debemos de arrancar tomcat con la siguiente línea de comandos:
catalina run
referencias:
http://stackoverflow.com/questions/6862696/redirect-tomcat-7-console-log-output-to-a-file-windows
miércoles, 26 de septiembre de 2012
Flex: operación trim() para los string
La operación trim() no aparece en la propia clase de String igual que en java, aquí tenemos que recurrir a la ayuda de StringUtil para conseguir esa función.
Es una clase estática con multitud de operacione, pero concretamente la que nos interesa sirve para eliminar los espacios en blanco del comienzo y final de un string.
Es una clase estática con multitud de operacione, pero concretamente la que nos interesa sirve para eliminar los espacios en blanco del comienzo y final de un string.
var token:String = " antuansoft "; StringUtil.trim(token)); //Salida: "antuansoft"
jueves, 30 de agosto de 2012
SpringSecurity: Truco para securizar URLS de tu aplicación
El parámetro "<sec:http pattern=" de Spring Security sirve para mapear las URL que atacan a nuestra aplicación y poderles aplicar seguridad a cada uno de ellos.
La experiencia aculada en nuestros proyectos nos ha llevado a la conclusión de que para configurar correctamente la seguridad de la aplicación y no tener problemas con las URL lo mejor es agrupar los patrones.
Nuestro sistema de seguridad consistía en que nosotros hacemos login contra un CAS server y una vez obtenida la autenticación este debía de redirigirnos a la aplicación a la que tenemos acceso. El problema era que aleatoriamente nos daba el acceso o no, generalmente nada más hacer log-in no nos daba acceso pero si recargábamos la página si nos daba acceso.
Nuestra configuración, erronea e incial era la siguiente:
La solución a este problema fue juntar los patrones e incluso segregarlos un poco más y diferenciar la distintas URLs
La experiencia aculada en nuestros proyectos nos ha llevado a la conclusión de que para configurar correctamente la seguridad de la aplicación y no tener problemas con las URL lo mejor es agrupar los patrones.
Nuestro sistema de seguridad consistía en que nosotros hacemos login contra un CAS server y una vez obtenida la autenticación este debía de redirigirnos a la aplicación a la que tenemos acceso. El problema era que aleatoriamente nos daba el acceso o no, generalmente nada más hacer log-in no nos daba acceso pero si recargábamos la página si nos daba acceso.
Nuestra configuración, erronea e incial era la siguiente:
<sec:http pattern="/messagebroker/**" security="none"/> <sec:http pattern="*.swf" security="none"/> <sec:http pattern="*.html" security="none"/> <sec:http entry-point-ref="entryPoint" auto-config="false" pattern="/*"> <sec:intercept-url pattern="/**" access="ROLE_AUTHENTICATED"/> </sec:http>
La solución a este problema fue juntar los patrones e incluso segregarlos un poco más y diferenciar la distintas URLs
<sec:http pattern="*.swf" security="none"/> <sec:http pattern="*.html" security="none"/> <sec:http pattern="/**"> <sec:anonymous enabled="true"/> <sec:intercept-url pattern="/messagebroker/**" access="ROLE_ANONYMOUS"/> <sec:intercept-url pattern="/access/login" access="ROLE_ANONYMOUS"/> <sec:intercept-url pattern="/access/loginsuccess" access="ROLE_AUTHENTICATED"/> <sec:form-login login-page="/access/login"/> </sec:http>
viernes, 24 de agosto de 2012
Flex: Recuperar el índice de un itemrenderer
Title: get de item index in a flex itemrenderer
Recuperar el índice de la posición que ocupa el itemrenderer que se está mostrando en pantalla es un cosa que no te preguntas hasta que realmente no te hace falta utlizarlo, aunque es de lo más básico
En internet hay varias opciones para hacerlo pero si ya estamos utlizando de Flex4 con la implementación Spak del itemrenderer es tan fácil como utilizar la propiedad itemIndex
Acordaros de poner el +1 para que la cuenta no empiece en 0.
Referencias:
http://www.jeffryhouser.com/index.cfm/2008/11/4/How-do-you-find-an-items-dataProvider-index-from-inside-an-itemRenderer
http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/spark/components/supportClasses/ItemRenderer.html#itemIndex
Recuperar el índice de la posición que ocupa el itemrenderer que se está mostrando en pantalla es un cosa que no te preguntas hasta que realmente no te hace falta utlizarlo, aunque es de lo más básico
En internet hay varias opciones para hacerlo pero si ya estamos utlizando de Flex4 con la implementación Spak del itemrenderer es tan fácil como utilizar la propiedad itemIndex
-- <?xml version="1.0" encoding="utf-8"?> <s:ItemRenderer............ <s:Group x="74" y="12"> <s:Rect x="0.5" y="0.5" width="20" height="20"> <s:stroke> <s:SolidColorStroke caps="none" color="#3085B7" joints="miter" miterLimit="10"/> </s:stroke> </s:Rect> <s:RichText id="numQuestion" x="8" y="6" color="#3085B7" columnCount="1" fontFamily="Myriad-Bold" fontSize="12.1205" kerning="on" lineHeight="76.1519" tabStops="S36" text="{itemIndex+1}" whiteSpaceCollapse="preserve"/> </s:Group> <s:RichText d:id="4" x="110" y="17" ai:aa="2" color="#414042" columnCount="1" fontFamily="DINPro-Regular" fontSize="14.1406" kerning="on" lineHeight="76.1519" tabStops="S199.772155761719" text="{data.question}" whiteSpaceCollapse="preserve"/> .............. </s:ItemRenderer> --
Acordaros de poner el +1 para que la cuenta no empiece en 0.
Referencias:
http://www.jeffryhouser.com/index.cfm/2008/11/4/How-do-you-find-an-items-dataProvider-index-from-inside-an-itemRenderer
http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/spark/components/supportClasses/ItemRenderer.html#itemIndex
jueves, 16 de agosto de 2012
Spring Data: Artículo imprescindible de introducción a Spring Data
Os dejo el enlace a este artículo que está muy bien para saber de que va el tema de Spring Data. Nosotros utilizamos SpringData Mongodb y SpringData redis.
http://www.infoq.com/articles/spring-data-intro
http://www.infoq.com/articles/spring-data-intro
Etiquetas:
Jpa,
MongoDB,
redis,
spring data
Ubicación:
Madrid, España
lunes, 13 de agosto de 2012
Eclipse: Incrementar el Console Buffer Size
Este es lo típico que nos va a ocurrir cuando java nos da una error con un montón de trazas y el buffer no da más de si.
Nada más fácil que ir a Windows>>Preferences>>Run/Debug>>Console
Y ahí encontraremos el buffer size para poner el que queramos.
Cuidado con lo que ponéis que lo guarda todo en memoria y si pones mucho empezará a chupar RAM y todo irá más lento.
Nada más fácil que ir a Windows>>Preferences>>Run/Debug>>Console
Y ahí encontraremos el buffer size para poner el que queramos.
Cuidado con lo que ponéis que lo guarda todo en memoria y si pones mucho empezará a chupar RAM y todo irá más lento.
viernes, 10 de agosto de 2012
MongoDB: java.lang.NoClassDefFoundError: com/google/common/base/Function
Este error se produce por no tener las versiones correctas de las librerías de Spring-data y query-dsl
Si investigamos un poco en google la clase que nos fata la podemos encontrar en un jar llamado guava-12.0.jar este error se soluciona pero nos da otro
Spring JPA MongoDB: java.lang.NoSuchMethodError: com.mysema.query.mongodb.MongodbQuery
-- java.lang.NoClassDefFoundError: com/google/common/base/Function at org.springframework.data.mongodb.repository.support.QueryDslMongoRepository.createQueryFor(QueryDslMongoRepository.java:167) at org.springframework.data.mongodb.repository.support.QueryDslMongoRepository.count(QueryDslMongoRepository.java:154) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:601) at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.executeMethodOn(RepositoryFactorySupport.java:334) at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.invoke(RepositoryFactorySupport.java:319) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172) at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:202) at $Proxy26.count(Unknown Source) at com.antuansoft.contentapi.application.CourseContentTemplateImpl.countByAllowedUsers(CourseContentTemplateImpl.java:61) at com.antuansoft.contentapi.integration.CourseContentTemplateIntegrationTest.countByAllowedUsers(CourseContentTemplateIntegrationTest.java:157) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:601) at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:45) at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15) at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:42) at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:20) at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:28) at org.springframework.test.context.junit4.statements.RunBeforeTestMethodCallbacks.evaluate(RunBeforeTestMethodCallbacks.java:74) at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:30) at org.springframework.test.context.junit4.statements.RunAfterTestMethodCallbacks.evaluate(RunAfterTestMethodCallbacks.java:83) at org.springframework.test.context.junit4.statements.SpringRepeat.evaluate(SpringRepeat.java:72) at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:231) at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:47) at org.junit.runners.ParentRunner$3.run(ParentRunner.java:231) at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:60) at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:229) at org.junit.runners.ParentRunner.access$000(ParentRunner.java:50) at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:222) at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61) at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:71) at org.junit.runners.ParentRunner.run(ParentRunner.java:300) at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:174) at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50) at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197) Caused by: java.lang.ClassNotFoundException: com.google.common.base.Function at java.net.URLClassLoader$1.run(URLClassLoader.java:366) at java.net.URLClassLoader$1.run(URLClassLoader.java:355) at java.security.AccessController.doPrivileged(Native Method) at java.net.URLClassLoader.findClass(URLClassLoader.java:354) at java.lang.ClassLoader.loadClass(ClassLoader.java:423) at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:308) at java.lang.ClassLoader.loadClass(ClassLoader.java:356) ... 43 more --
Si investigamos un poco en google la clase que nos fata la podemos encontrar en un jar llamado guava-12.0.jar este error se soluciona pero nos da otro
-- java.lang.NoSuchMethodError: com.mysema.query.mongodb.MongodbQuery.<init>(Lcom/mongodb/DBCollection;Lcom/google/common/base/Function;Lcom/mysema/query/mongodb/MongodbSerializer;)V at org.springframework.data.mongodb.repository.support.SpringDataMongodbQuery.<init>(SpringDataMongodbQuery.java:58) at org.springframework.data.mongodb.repository.support.SpringDataMongodbQuery.<init>(SpringDataMongodbQuery.java:44) at org.springframework.data.mongodb.repository.support.QueryDslMongoRepository.createQueryFor(QueryDslMongoRepository.java:167) at org.springframework.data.mongodb.repository.support.QueryDslMongoRepository.count(QueryDslMongoRepository.java:154) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:601) at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.executeMethodOn(RepositoryFactorySupport.java:334) at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.invoke(RepositoryFactorySupport.java:319) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172) at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:202) --Para este error ya tengo un post publicado que este:
Spring JPA MongoDB: java.lang.NoSuchMethodError: com.mysema.query.mongodb.MongodbQuery
jueves, 9 de agosto de 2012
MongoDB Spring Data: Push de objetos en Arrays
Push an Object into an array (addToSet)
Si trabajáis con MongoDB ya sabréis que podemos utilizar el comando push para introducir valores en un arrary.
Por ejemplo si tenemos el siguiente objecto mapeado en MongoDB
Si queremos introducir un valor String en el array de tags es tan fácil como hace esto
El resultado en MongoDb debería ser algo parecido a esto
Al insertar en el array de tags objetos de la clase String no hay ningún problema ya que los entiende perfectamente.
El problema que he encontrado ocurre cuando tienes que insertar en el array Objectos de alguna clase que no sean tipos básicos. Por ejemplo un objecto de la clase User.
El problema que ocurre es que al insertarlo de la misma manera que un String normal no transforma el objeto y no pone las propiedades ni "_id" ni "_class", o sea que no lo transforma e introduce sólo las propiedades que tenga ese objeto en el array.
Para solucionar esto utilizamos una par de instrucciones que fuerzan a MongoDb a realizar esta transformación.
Si trabajáis con MongoDB ya sabréis que podemos utilizar el comando push para introducir valores en un arrary.
Por ejemplo si tenemos el siguiente objecto mapeado en MongoDB
import org.springframework.data.annotation.Id; import org.springframework.data.mongodb.core.mapping.Document; import com.google.code.morphia.annotations.Entity; @Entity @Document public class Course implements Serializable { private static final long serialVersionUID = -7251789829032925885L; @Id private String id = UUID.randomUUID().toString(); private String name; private String description; private long creationDate = new Date().getTime(); private int duration; private int credits; private List<String> tags = new ArrayList<String>(); private List<String> users = new ArrayList<User>();
Si queremos introducir un valor String en el array de tags es tan fácil como hace esto
public void addTag(String courseId, String tag){ WriteResult wr = mongoOperations.updateFirst( new Query(where("id").is(courseId)), new Update().push("tags", tag),Course.class); }
El resultado en MongoDb debería ser algo parecido a esto
{"_class": "com.antuansoft.Course", "_id": "953a878e-5aa6-4811-82e3-660b00ebafe2", "creationDate": 1344439353237, "credits": 10, "description": "Course DESCRIPTION", "duration": 100, "name": "Course 1", "tags": { "0": "tag1" "1": "tag2" }}
Al insertar en el array de tags objetos de la clase String no hay ningún problema ya que los entiende perfectamente.
El problema que he encontrado ocurre cuando tienes que insertar en el array Objectos de alguna clase que no sean tipos básicos. Por ejemplo un objecto de la clase User.
El problema que ocurre es que al insertarlo de la misma manera que un String normal no transforma el objeto y no pone las propiedades ni "_id" ni "_class", o sea que no lo transforma e introduce sólo las propiedades que tenga ese objeto en el array.
Para solucionar esto utilizamos una par de instrucciones que fuerzan a MongoDb a realizar esta transformación.
DBObject dbo = new BasicDBObject(); mongoOperations.getConverter().write(user, dbo);
public void addUser(String idCourse, User user){ DBObject dbo = new BasicDBObject(); mongoOperations.getConverter().write(user, dbo); WriteResult wr = mongoOperations.updateFirst( new Query(where("id").is(idCourse)), new Update().push("users", dbo),Course.class);
{"_class": "com.antuansoft.Course", "_id": "953a878e-5aa6-4811-82e3-660b00ebafe2", "creationDate": 1344439353237, "credits": 10, "description": "Course DESCRIPTION", "duration": 100, "name": "Course 1", "tags": { "0": "tag1" "1": "tag2" } "users": { "0": { "_class": "com.antuansoft.User", "_id": "047cd911-356a-4851-948a-3087ea735353", "name": "AntuanSoft" } } }Nota: Si no queremos que aparezcan valores repetidos en nuestra lista de objetos/strings lo mejor es utilizar el método addToSet en vez de push. De este modo si introducimos un valor que ya existe, este no se insetará
viernes, 27 de julio de 2012
MongoDb: DataAccessResourceFailureException
Configurando uno de nuestros test sobre los datos almacenados en MongoDB sobre un nuevo dbmane (database-test) no creado ya en MongoDB me ha dado el siguiente error:
La configuración utilizada fue la siguiente:
El error se produce cuando no tengo creada de antemano la base de datos de mongo, si la base de datos ya está creada no hay problema.
Parece que Spring Data al crearla y al intentar acceder a la base de datos recien creada recibe un error del driver de MongoDb y a fecha de hoy 27/07/2012 (driver version: 2.7.3) existe un bug en este apartado.
Como referencia os dejo esta entrada en el JIRA de MongoDB en su versión del driver para java.
mongo driver should check whether socket still be available before use it?
-- org.springframework.dao.DataAccessResourceFailureException: can't say something; nested exception is com.mongodb.MongoException$Network: can't say something at org.springframework.data.mongodb.core.MongoExceptionTranslator.translateExceptionIfPossible(MongoExceptionTranslator.java:56) at org.springframework.data.mongodb.core.MongoTemplate.potentiallyConvertRuntimeException(MongoTemplate.java:1545) at org.springframework.data.mongodb.core.MongoTemplate.execute(MongoTemplate.java:368) at org.springframework.data.mongodb.core.MongoTemplate.doRemove(MongoTemplate.java:928) at org.springframework.data.mongodb.core.MongoTemplate.remove(MongoTemplate.java:919) at org.springframework.data.mongodb.repository.support.SimpleMongoRepository.delete(SimpleMongoRepository.java:137) at org.springframework.data.mongodb.repository.support.SimpleMongoRepository.delete(SimpleMongoRepository.java:146) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:601) at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.executeMethodOn(RepositoryFactorySupport.java:334) at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.invoke(RepositoryFactorySupport.java:319) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172) at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:202) at $Proxy52.delete(Unknown Source) --
La configuración utilizada fue la siguiente:
-- <?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:flex="http://www.springframework.org/schema/flex" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:p="http://www.springframework.org/schema/p" xmlns:security="http://www.springframework.org/schema/security" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:mongo="http://www.springframework.org/schema/data/mongo" xmlns:jpa="http://www.springframework.org/schema/data/jpa" xmlns:task="http://www.springframework.org/schema/task" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/data/mongo http://www.springframework.org/schema/data/mongo/spring-mongo-1.0.xsd http://www.springframework.org/schema/flex http://www.springframework.org/schema/flex/spring-flex-1.5.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-3.0.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd http://www.springframework.org/schema/data/jpa http://www.springframework.org/schema/data/jpa/spring-jpa.xsd"> <mongo:mongo host="apps.stratmind.net" port="27017" id="mongo"> <mongo:options connections-per-host="8" threads-allowed-to-block-for-connection-multiplier="4" connect-timeout="1000" max-wait-time="1500" auto-connect-retry="true" socket-keep-alive="true" socket-timeout="1500" slave-ok="true" write-number="1" write-timeout="0" write-fsync="true"/> </mongo:mongo> <mongo:repositories base-package="com.antuansoft.mongo"/> <mongo:db-factory dbname="database-test" mongo-ref="mongo" id="mongoDbFactory"/> <bean id="mongoTemplate" class="org.springframework.data.mongodb.core.MongoTemplate"> <constructor-arg name="mongoDbFactory" ref="mongoDbFactory"/> <property name="writeResultChecking" value="EXCEPTION"/><!-- propiedad usada para que si hay error devuelva una excepción y no haya que comprobarlo --> </bean> </beans> --
El error se produce cuando no tengo creada de antemano la base de datos de mongo, si la base de datos ya está creada no hay problema.
Parece que Spring Data al crearla y al intentar acceder a la base de datos recien creada recibe un error del driver de MongoDb y a fecha de hoy 27/07/2012 (driver version: 2.7.3) existe un bug en este apartado.
Como referencia os dejo esta entrada en el JIRA de MongoDB en su versión del driver para java.
mongo driver should check whether socket still be available before use it?
jueves, 26 de julio de 2012
Problemas típicos de configuración de los Repositories de JPA y Mongodb combinados
Typical problems configuring JPA and Mongodb Repositories together
Utilizando Spring Data tenemos la posibilidad de acceder fácilmente a datos almacenados en base de datos relacionales como Mysql, Postgres, etc.. a través de Spring data JPA y también a base de datos NoSQL como por ejemplo MongoDB con Spring Data MongoDB.
Una de las principales carácterísticas de Spring Data es que ya no es necesaria la generación de classes DAO con las opreciones básicas como save, delete, update y find ya que ya vienen implementadas por defecto.
Para que eso funcione creamos una interfaz que heredará de una clase de Spring Data y ya tendrá todas las operaciones disponibles.
JPA (AnnouncementDao.java)
MongoDB (CompanuDao.java)
Para que estos daos funcionen correctamente en nuestro contexto de Spring tenemos que configurarlo en los xml a través de unos repositories que mapeen estas interfaces indicándole en la opción base-package que páquete(o alguno de sus hijos) contienen los DAOS.
Ambas opciones podemos combinarlas en nuestra arquitectura de datos pero lo normal cuando integramos las dos maneras de acceso dentro de un mismo proyecto es que nos den los siguientes errores:
1º Error típico:
Este error ocurre por que JPA ha mapeado un DAO de Mongodb, esto ocurre cuando el base-package de ambas configuraciones es el mismo o el de mongo está dentro del de JPA. Por lo tanto JPA intentará configurar un DAO de Mongodb y no podrá procesar la Clase Company que es de Mongobd.
La configuración correcta sería que los paquetes donde están los daos sean distintos y no estén anidados.
JPA
Mongodb
2º Error típico:
El pojo del interface DAO no está configurados correctamente a través de la etiqueta @Entity
Los pojos de JPA utilizan la @Entity
Los pojos de MongoDB utilizan la @Entity
Si configuramos un pojo de MongoDb con una entity de JPA nos dará el siguiente error
Para finalizar os dejo unas referencias interesantes para ver como realizar estas configuraciones básicas.
Configuración basica de Spring Data Mongobd (mirad las otras 2 partes tb están bien)
Capa de persistencia con Spring Data JPA
Utilizando Spring Data tenemos la posibilidad de acceder fácilmente a datos almacenados en base de datos relacionales como Mysql, Postgres, etc.. a través de Spring data JPA y también a base de datos NoSQL como por ejemplo MongoDB con Spring Data MongoDB.
Una de las principales carácterísticas de Spring Data es que ya no es necesaria la generación de classes DAO con las opreciones básicas como save, delete, update y find ya que ya vienen implementadas por defecto.
Para que eso funcione creamos una interfaz que heredará de una clase de Spring Data y ya tendrá todas las operaciones disponibles.
JPA (AnnouncementDao.java)
- package com.antuansoft.daos.jpa import org.springframework.data.jpa.repository.JpaRepository; import com.antuansoft.Announcement; public interface AnnouncementDao extends JpaRepository<Announcement, String>, CustomAnnouncementDao{ } --
MongoDB (CompanuDao.java)
- package com.antuansoft.daos.mongodb import java.util.List; import org.springframework.data.mongodb.repository.MongoRepository; import org.springframework.data.querydsl.QueryDslPredicateExecutor; import com.antuansoft.pojo.Company; public interface CompanyDao extends MongoRepository<Company, String>, QueryDslPredicateExecutor<Company>{ } --
Para que estos daos funcionen correctamente en nuestro contexto de Spring tenemos que configurarlo en los xml a través de unos repositories que mapeen estas interfaces indicándole en la opción base-package que páquete(o alguno de sus hijos) contienen los DAOS.
Ambas opciones podemos combinarlas en nuestra arquitectura de datos pero lo normal cuando integramos las dos maneras de acceso dentro de un mismo proyecto es que nos den los siguientes errores:
1º Error típico:
- Caused by: java.lang.IllegalArgumentException: Not an managed type: class com.antuansoft.pojos.Company at org.hibernate.ejb.metamodel.MetamodelImpl.managedType(MetamodelImpl.java:171) at org.springframework.data.jpa.repository.support.JpaMetamodelEntityInformation.<init>(JpaMetamodelEntityInformation.java:58) at org.springframework.data.jpa.repository.support.JpaEntityInformationSupport.getMetadata(JpaEntityInformationSupport.java:65) at org.springframework.data.jpa.repository.support.JpaRepositoryFactory.getEntityInformation(JpaRepositoryFactory.java:149) at org.springframework.data.jpa.repository.support.JpaRepositoryFactory.getTargetRepository(JpaRepositoryFactory.java:87) at org.springframework.data.jpa.repository.support.JpaRepositoryFactory.getTargetRepository(JpaRepositoryFactory.java:70) at org.springframework.data.repository.core.support.RepositoryFactorySupport.getRepository(RepositoryFactorySupport.java:137) at org.springframework.data.repository.core.support.RepositoryFactoryBeanSupport.getObject(RepositoryFactoryBeanSupport.java:125) at org.springframework.data.repository.core.support.RepositoryFactoryBeanSupport.getObject(RepositoryFactoryBeanSupport.java:41) at org.springframework.beans.factory.support.FactoryBeanRegistrySupport.doGetObjectFromFactoryBean(FactoryBeanRegistrySupport.java:142) ... 63 more --
Este error ocurre por que JPA ha mapeado un DAO de Mongodb, esto ocurre cuando el base-package de ambas configuraciones es el mismo o el de mongo está dentro del de JPA. Por lo tanto JPA intentará configurar un DAO de Mongodb y no podrá procesar la Clase Company que es de Mongobd.
La configuración correcta sería que los paquetes donde están los daos sean distintos y no estén anidados.
JPA
- <jpa:repositories base-package="com.antuansoft.daos.jpa"></jpa:repositories> --
Mongodb
- <mongo:repositories base-package="com.antuansoft.daos.mongodb"/> --
2º Error típico:
El pojo del interface DAO no está configurados correctamente a través de la etiqueta @Entity
Los pojos de JPA utilizan la @Entity
- import javax.persistence.Entity; --
Los pojos de MongoDB utilizan la @Entity
- import com.google.code.morphia.annotations.Entity; --
Si configuramos un pojo de MongoDb con una entity de JPA nos dará el siguiente error
- Caused by: org.hibernate.AnnotationException: No identifier specified for entity: com.antuansoft.pojos.Company at org.hibernate.cfg.InheritanceState.determineDefaultAccessType(InheritanceState.java:268) at org.hibernate.cfg.InheritanceState.getElementsToProcess(InheritanceState.java:223) at org.hibernate.cfg.AnnotationBinder.bindClass(AnnotationBinder.java:686) at org.hibernate.cfg.Configuration$MetadataSourceQueue.processAnnotatedClassesQueue(Configuration.java:3977) at org.hibernate.cfg.Configuration$MetadataSourceQueue.processMetadata(Configuration.java:3931) at org.hibernate.cfg.Configuration.secondPassCompile(Configuration.java:1368) at org.hibernate.cfg.Configuration.buildMappings(Configuration.java:1345) at org.hibernate.ejb.Ejb3Configuration.buildMappings(Ejb3Configuration.java:1477) at org.hibernate.ejb.EventListenerConfigurator.configure(EventListenerConfigurator.java:193) at org.hibernate.ejb.Ejb3Configuration.configure(Ejb3Configuration.java:1096) at org.hibernate.ejb.Ejb3Configuration.configure(Ejb3Configuration.java:685) at org.hibernate.ejb.HibernatePersistence.createContainerEntityManagerFactory(HibernatePersistence.java:73) at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.createNativeEntityManagerFactory(LocalContainerEntityManagerFactoryBean.java:268) at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.afterPropertiesSet(AbstractEntityManagerFactoryBean.java:310) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1514) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1452) --
Para finalizar os dejo unas referencias interesantes para ver como realizar estas configuraciones básicas.
Configuración basica de Spring Data Mongobd (mirad las otras 2 partes tb están bien)
Capa de persistencia con Spring Data JPA
martes, 24 de julio de 2012
StringTokenizer en Flex
Buscando buscando encontré un código firmado por Alex Ciobanu y que lo tiene en una librería con otras funcionalidades para obtener la misma funcionalidad de Stringtokenizer de Java.
Toda esta funcionalidad está en la librería fxmaker
Como sólo me interesaba la parte del manejo de la cadena miré el código fuente y lo utilicé.
Por si os es útil os dejo la referencia a la librería y al código fuente del StringTokenizer.
Y también os pego el código aquí por si acaso en algún momento desaparece, ya que me parece bastante útil.
Toda esta funcionalidad está en la librería fxmaker
Como sólo me interesaba la parte del manejo de la cadena miré el código fuente y lo utilicé.
Por si os es útil os dejo la referencia a la librería y al código fuente del StringTokenizer.
Y también os pego el código aquí por si acaso en algún momento desaparece, ya que me parece bastante útil.
--
/** |
* |
* @author Alexutz |
* |
*/ |
public class StringTokenizer |
{ |
private var tokens : Array; |
private var currentToken : int = -1; |
/** |
* |
* |
*/ |
public function StringTokenizer(delimiter : String = null, value: String = null){ |
tokenize(value, delimiter); |
} |
/** |
* |
* @return |
* |
*/ |
public function hasMoreTokens() : Boolean{ |
return tokens && currentToken < tokens.length - 1; |
} |
/** |
* |
* @return |
* |
*/ |
public function getToken() : String{ |
if(currentToken >= tokens.length - 1){ |
throw new Error(""); |
} |
currentToken++; |
var token : String = tokens[currentToken] as String; |
return token; |
} |
/** |
* |
* @param value |
* @param delimiter |
* |
*/ |
public function tokenize(value : String, delimiter : String) : void{ |
if(value == null || delimiter == null){ |
return; |
} |
tokens = value.split(delimiter); |
currentToken = -1; |
} |
} |
Software útil: Winsplit Revolution
Este software una vez instalado te permite cambiar la disposición de la ventana activa en la pantalla.
Yo lo encuentro bastante útil porque tengo dos monitores y puedo pasar la ventana de uno a otro con una simple combinación de teclas.
CTRL + ALT + flecha derecha --- pasa la ventana al monitor 2.
CTRL + ALT + flecha izquierda--- pasa la ventana al monitor 1.
CTRL + ALT + números de teclado numérico --- colocala ventana en una posición relativa al número que pulses.
http://winsplit-revolution.com/home
Yo lo encuentro bastante útil porque tengo dos monitores y puedo pasar la ventana de uno a otro con una simple combinación de teclas.
CTRL + ALT + flecha derecha --- pasa la ventana al monitor 2.
CTRL + ALT + flecha izquierda--- pasa la ventana al monitor 1.
CTRL + ALT + números de teclado numérico --- colocala ventana en una posición relativa al número que pulses.
http://winsplit-revolution.com/home
miércoles, 11 de julio de 2012
Spring Data y QueryDSL operador like
QueryDSL like operator
Prerrequisitos: Conocimientos medios de QueryDsl.
El problema que resolvemos a continuación es el operador like usando QueryDSL. Si no quieres leerte todo el rollo te adelanto que el operador que buscas es containsIgnoreCase en vez de like pero tiene alguna pega que expongo a continuación.
Si has llegado hasta aquí buscando por google supongo que ya tendrás configurado tu entorno y QueryDsl para realizar tus consultas. Como ya sabemos la ventaja que te da QueryDsl es nos permite construir una query directamente sobre el código java de nuestro service.
Imaginemos que tenemos el siguiente pojo
Una vez configurado QueryDsl automáticamente nos lo transforma nuestro pojo en el siguiente código.
Esto nos permite hacer queries directamente con código java
El problema es cuando queremos hacer una búsqueda sobre un campo String con lo que en SQL sería el operador LIKE, como por ejemplo Name like %Matematica%
QueryDsl tiene el operador like pero su lo utilizamos nos da el siguiente error:
La alternativa para que la operación sea la que deseamos es containsIgnoreCase
Esta búsqueda recuperará cualquier palabra en el nombre que contenga Matemati como por ejemplo, Matematica, Matematico, Matematicas ya esté en mayúsculas o minúsculas.
Lo que no encontrará este tipo de búsqueda son acentos, por ejemplo Matemáticas, así que no es una búsqueda full text pero se aproxima bastante.
Prerrequisitos: Conocimientos medios de QueryDsl.
El problema que resolvemos a continuación es el operador like usando QueryDSL. Si no quieres leerte todo el rollo te adelanto que el operador que buscas es containsIgnoreCase en vez de like pero tiene alguna pega que expongo a continuación.
Si has llegado hasta aquí buscando por google supongo que ya tendrás configurado tu entorno y QueryDsl para realizar tus consultas. Como ya sabemos la ventaja que te da QueryDsl es nos permite construir una query directamente sobre el código java de nuestro service.
Imaginemos que tenemos el siguiente pojo
---- @Entity @Document public class Course implements Serializable { private static final long serialVersionUID = -7251789829032925885L; @Id private String id = UUID.randomUUID().toString(); private String name; private String description; private String companyOwner; private String metodology; ---
Una vez configurado QueryDsl automáticamente nos lo transforma nuestro pojo en el siguiente código.
---- /** * QCourse is a Querydsl query type for Course */ @Generated("com.mysema.query.codegen.EntitySerializer") public class QCourse extends EntityPathBase<Course> { private static final long serialVersionUID = 430564814; public static final QCourse course = new QCourse("course"); public final StringPath companyOwner = createString("companyOwner"); public final StringPath description = createString("description"); public final StringPath id = createString("id"); public final StringPath metodology = createString("metodology"); public QCourse(String variable) { super(Course.class, forVariable(variable)); } public QCourse(Path<? extends Course> entity) { super(entity.getType(), entity.getMetadata()); } public QCourse(PathMetadata<?> metadata) { super(Course.class, metadata); } ---
Esto nos permite hacer queries directamente con código java
---- BooleanBuilder builder = new BooleanBuilder(); builder.and(QCourse.course.id.eq("id1")); builder.and(QCourse.course.name.like("Matematica")); List<Course> data = (List<Course>) courseDao.findAll(builder.getValue()); return data; ---
El problema es cuando queremos hacer una búsqueda sobre un campo String con lo que en SQL sería el operador LIKE, como por ejemplo Name like %Matematica%
QueryDsl tiene el operador like pero su lo utilizamos nos da el siguiente error:
---- java.lang.UnsupportedOperationException: Illegal operation course.name like Matemáticas at com.mysema.query.mongodb.MongodbSerializer.visit(MongodbSerializer.java:225) at com.mysema.query.mongodb.MongodbSerializer.visit(MongodbSerializer.java:34) at com.mysema.query.types.expr.BooleanOperation.accept(BooleanOperation.java:52) at com.mysema.query.mongodb.MongodbSerializer.handle(MongodbSerializer.java:39) at com.mysema.query.mongodb.MongodbSerializer.visit(MongodbSerializer.java:98) at com.mysema.query.mongodb.MongodbSerializer.visit(MongodbSerializer.java:34) at com.mysema.query.types.OperationImpl.accept(OperationImpl.java:81) at com.mysema.query.mongodb.MongodbSerializer.handle(MongodbSerializer.java:39) at com.mysema.query.mongodb.MongodbQuery.createQuery(MongodbQuery.java:330) at com.mysema.query.mongodb.MongodbQuery.createCursor(MongodbQuery.java:240) at com.mysema.query.mongodb.MongodbQuery.createCursor(MongodbQuery.java:235) at com.mysema.query.mongodb.MongodbQuery.list(MongodbQuery.java:221) at org.springframework.data.mongodb.repository.support.QueryDslMongoRepository.findAll(QueryDslMongoRepository.java:113) ---
La alternativa para que la operación sea la que deseamos es containsIgnoreCase
---- builder.and(QCourse.course.name.containsIgnoreCase("Matemati")); ---
Esta búsqueda recuperará cualquier palabra en el nombre que contenga Matemati como por ejemplo, Matematica, Matematico, Matematicas ya esté en mayúsculas o minúsculas.
Lo que no encontrará este tipo de búsqueda son acentos, por ejemplo Matemáticas, así que no es una búsqueda full text pero se aproxima bastante.
miércoles, 4 de julio de 2012
Spring Data Mongodb Configurando WriteResultChecking Policy para lanzar excepciones
Setting WriteResultChecking Policy in order to throw Exceptions
Cuando trabajamos con Mongodb a la hora de hacer Queries debemos de comprobar el objeto WriteResult resultante para comprobar que la operación se ha realizado correctamente.
Para que no tengmos que hacer esto y si ocurre algún problema se lance una excepcion debemos de configurar Spring Data Mongo Db de la siguiente manera.
La clave está en la propiedad writeResultChecking que puede configurar con los valores NONE, LOG y EXCEPTION que es el caso que nos interesa.
Referencias:
Spring data mongo de documentacion
Ejemplo de configuración
Cuando trabajamos con Mongodb a la hora de hacer Queries debemos de comprobar el objeto WriteResult resultante para comprobar que la operación se ha realizado correctamente.
WriteResult wr = mongoOperations.updateFirst( new Query(where("id").is("objectId")), new Update().push("favouriteUsers", idUser),Course.class); String error = wr.getError();
Para que no tengmos que hacer esto y si ocurre algún problema se lance una excepcion debemos de configurar Spring Data Mongo Db de la siguiente manera.
<mongo:mongo host="localhost" port="27017" id="mongo"> <mongo:options connections-per-host="8" threads-allowed-to-block-for-connection-multiplier="4" connect-timeout="1000" max-wait-time="1500" auto-connect-retry="true" socket-keep-alive="true" socket-timeout="1500" slave-ok="true" write-number="1" write-timeout="0" write-fsync="true"/> </mongo:mongo> <mongo:repositories base-package="xx.xxxx.xxx"/> <mongo:db-factory dbname="database" mongo-ref="mongo" id="mongoDbFactory"/> <bean id="mongoTemplate" class="org.springframework.data.mongodb.core.MongoTemplate"> <constructor-arg name="mongoDbFactory" ref="mongoDbFactory"/> <property name="writeResultChecking" value="EXCEPTION"/> <!-- propiedad usada para que si hay error devuelva una excepción y no haya que comprobarlo --> </bean>
La clave está en la propiedad writeResultChecking que puede configurar con los valores NONE, LOG y EXCEPTION que es el caso que nos interesa.
Referencias:
Spring data mongo de documentacion
Ejemplo de configuración
miércoles, 27 de junio de 2012
Flex - itemCreationPolicy: La política de creación de un objeto es útil
Pre-requisitos: Conocimientos básicos de Flex.
Esta particularidad de Flex es bastante útil desde mi punto de vista por dos puntos principalmente.
El comportamiento deferred es el que está puesto por defecto ya que si fuera al contrario y todos los componentes cargaran en nuestra aplicación esta podría consumir mucha memoria y perder rendimiento.
Los que tienen el valor deferred se crean cuando el objeto es instanciado es decir cuando aparece en pantalla y el objeto tes visible.
Pero en ciertos casos necesitamos que este objeto aunque no se vea en pantalla necesitamos que se cree para que por ejemplo se carguen en él unos datos recuperados de base de datos o que al cargase se ejecute algún evento que necesitemos que ocurra.
En estos casos lo mejor es poner el campo itemCreationPolicy="immediate" para que aunque no sea visible se comporte como si lo fuera y se cree al cargase la pantalla.
Todos los componentes de flex tienen esta propiedad itemCreationPolicy y puede aplicase cuando se crea necesario:
Referencias:
http://help.adobe.com/en_US/flex/using/WS2db454920e96a9e51e63e3d11c0bf63611-7ffa.html
Esta particularidad de Flex es bastante útil desde mi punto de vista por dos puntos principalmente.
- Para ahorrar memoria.
- Para mejorar el comportamiento al a vista del usuario.
- Deferred: Que hace que el objeto se cree cuando es instaciado. Valor por defecto
- Inmediate: Que hace que el objeto se cree al inciar la aplicación.
El comportamiento deferred es el que está puesto por defecto ya que si fuera al contrario y todos los componentes cargaran en nuestra aplicación esta podría consumir mucha memoria y perder rendimiento.
Los que tienen el valor deferred se crean cuando el objeto es instanciado es decir cuando aparece en pantalla y el objeto tes visible.
Pero en ciertos casos necesitamos que este objeto aunque no se vea en pantalla necesitamos que se cree para que por ejemplo se carguen en él unos datos recuperados de base de datos o que al cargase se ejecute algún evento que necesitemos que ocurra.
En estos casos lo mejor es poner el campo itemCreationPolicy="immediate" para que aunque no sea visible se comporte como si lo fuera y se cree al cargase la pantalla.
Todos los componentes de flex tienen esta propiedad itemCreationPolicy y puede aplicase cuando se crea necesario:
<s:Button id="newButtonImmediate" includeIn="Immediate" itemCreationPolicy="immediate"/>
Referencias:
http://help.adobe.com/en_US/flex/using/WS2db454920e96a9e51e63e3d11c0bf63611-7ffa.html
jueves, 21 de junio de 2012
Flex - Eclipse: Modificar el Context Root en una aplicación
Modify the application´s context root
En las primeras versiones del Flex Plugin para la integración del entorno con Eclipse podíamos modificar el context root en alguna de las pantallas de configuración como Flex Compiler o Flex Build Path.
Pero actualmente en la última versión del plugin a día de hoy la versión 4.6 no es posible modificarlo.
Para ello lo que hago es abrir el archivo ".flexProperties" que está oculto y tenemos que hacer que aparezca, para ellos pinchamos en el botón que tiene las flechas
abrimos el archivo y en el apartado serverContextRoot ponemos el contexto que queramos.
serverContextRoot ="/MyContextRoot".
Hay que tener cuidado porque a veces al modificar alguno de los apartados de la configuración de Flex del proyecto este archivo puede volverse a modificar y volver a si valor original que es
serverContextRoot ="/WebContent"
Hay acordarse de hacer un build de la aplicación(build) para que la compilar la aplicación este parámetro se incorpore.
Esto principalmente puede servir para configurar las llamadas al protocolo amf cuando hacemos llamadas a servicios remotos,
http://localhost:8080/MyContextRoot/messagebroker/amf
http://localhost:8080/WebContent/messagebroker/amf
En las primeras versiones del Flex Plugin para la integración del entorno con Eclipse podíamos modificar el context root en alguna de las pantallas de configuración como Flex Compiler o Flex Build Path.
Pero actualmente en la última versión del plugin a día de hoy la versión 4.6 no es posible modificarlo.
Para ello lo que hago es abrir el archivo ".flexProperties" que está oculto y tenemos que hacer que aparezca, para ellos pinchamos en el botón que tiene las flechas
abrimos el archivo y en el apartado serverContextRoot ponemos el contexto que queramos.
serverContextRoot ="/MyContextRoot".
Hay que tener cuidado porque a veces al modificar alguno de los apartados de la configuración de Flex del proyecto este archivo puede volverse a modificar y volver a si valor original que es
serverContextRoot ="/WebContent"
Hay acordarse de hacer un build de la aplicación(build) para que la compilar la aplicación este parámetro se incorpore.
Esto principalmente puede servir para configurar las llamadas al protocolo amf cuando hacemos llamadas a servicios remotos,
http://localhost:8080/MyContextRoot/messagebroker/amf
http://localhost:8080/WebContent/messagebroker/amf
lunes, 18 de junio de 2012
Spring JPA MongoDB: java.lang.NoSuchMethodError: com.mysema.query.mongodb.MongodbQuery
En nuestros proyecto estamos estamos trabajando con Spring Data Jpa para MySql y para MongoDb.
Al hora de hacer una query en MongoDb utilizando QueryDSL para utilizar los predicado que facilitan la creación de queries, nos ha dado el siguiente error.
El error proviene al hacer una query como esta:
El problema consistía en un problema de versiones entre los jar de
Las versiones de los Jars fueron las siguientes a fecha (18/06/2012)
Al hora de hacer una query en MongoDb utilizando QueryDSL para utilizar los predicado que facilitan la creación de queries, nos ha dado el siguiente error.
------ java.lang.NoSuchMethodError: com.mysema.query.mongodb.MongodbQuery.<init>(Lcom/mongodb/DBCollection;Lcom/google/common/base/Function;Lcom/mysema/query/mongodb/MongodbSerializer;)V at org.springframework.data.mongodb.repository.support.SpringDataMongodbQuery.<init>(SpringDataMongodbQuery.java:58) at org.springframework.data.mongodb.repository.support.SpringDataMongodbQuery.<init>(SpringDataMongodbQuery.java:44) at org.springframework.data.mongodb.repository.support.QueryDslMongoRepository.createQueryFor(QueryDslMongoRepository.java:167) at org.springframework.data.mongodb.repository.support.QueryDslMongoRepository.count(QueryDslMongoRepository.java:154) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:601) at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.executeMethodOn(RepositoryFactorySupport.java:334) at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.invoke(RepositoryFactorySupport.java:319) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172) at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:202) -----El código utilizado el el siguiente:
import org.springframework.data.mongodb.repository.MongoRepository; import org.springframework.data.querydsl.QueryDslPredicateExecutor; import charris.example.domain.Product; public interface ProductRepository extends MongoRepository<Product, String>, QueryDslPredicateExecutor<Product> { }
El error proviene al hacer una query como esta:
ProductRepository repo = context.getBean(ProductRepository.class); Product p = repo.findOne(QProduct.product.name.eq("ProductName"));
El problema consistía en un problema de versiones entre los jar de
- querydl-mongodb
- spring-data
Las versiones de los Jars fueron las siguientes a fecha (18/06/2012)
- querydsl-mongodb-2.5.0.jar
- querydsl-mongodb-2.5.0-apt.jar
- querydsl-mongodb-2.5.0-apt-one-jar.jar
- spring-data-commons-core-1.3.2.BUILD-20120618.140513-1.jar
- spring-data-jpa-1.1.1.BUILD-20120606.192912-1.jar
- spring-data-mongodb-1.1.0.BUILD-20120614.104654-40.jar
lunes, 11 de junio de 2012
ANT: Tratamiento de Strings en ANT con AntelopeTasks
Managing Strings with ANT (Antelope Tasks)
pre-requisitos: Conocimientos de ANT y algo de configuración de librerías auxiliares de ANT;
Cuando la funcionalidad básica de de ANT se queda corta es necesario utilizar otras librerías auxiliares que nos dan la funcionalidad extra que no tenemos con las librerías básicas de ANT.
Como ejemplos tenemos:
Una vez descargado el .jar de Antelope podemos consultar la documentación de instalación de las tareas adicionales y podemos ver que la configuración es puede hacer de dos maneras:
A la hora de utilizar la funcionalidad es tan sencillo como fijarse en los ejemplos que trae la documentación, os dejo el ejemplo del lowercase.
Es muy sencillo en la propiedad project_name_lowecase se guardará el contenido transformado en minúsculas que venga en la propiedad project_name.
pre-requisitos: Conocimientos de ANT y algo de configuración de librerías auxiliares de ANT;
Cuando la funcionalidad básica de de ANT se queda corta es necesario utilizar otras librerías auxiliares que nos dan la funcionalidad extra que no tenemos con las librerías básicas de ANT.
Como ejemplos tenemos:
- ant-contrib: Aporta tareas para programar con ant más fácilmente (if, foreach,etc..)
- Antelope: Aparte de una interfaz gráfica, tiene una amplia gama de tareas en mi caso el tratamiento de Strings que es el que he utilizado.
Una vez descargado el .jar de Antelope podemos consultar la documentación de instalación de las tareas adicionales y podemos ver que la configuración es puede hacer de dos maneras:
- La fácil: Copiando el Jar en el directorio lib donde tengamos instalado ant. Pero a mi no me gusta este método porque me interesa que tendría que hacer esto en cada equipo y también en la instalación de Ant del servidor de integración. Prefiero que esta configuración esté dentro de los archivos de mi proyecto.
- La más independiente: Referenciando al archivo jar de antelope y la tarea que voy a usar en mi script de Ant.
<?xml version="1.0" encoding="UTF-8"?> <project default="run" basedir="." name="GX2 Packager"> <taskdef name="stringutil" classname="ise.antelope.tasks.StringUtilTask"> <classpath> <pathelement location="${AntLibs}/AntelopeTasks_3.5.1.jar"/> </classpath> </taskdef>
A la hora de utilizar la funcionalidad es tan sencillo como fijarse en los ejemplos que trae la documentación, os dejo el ejemplo del lowercase.
Es muy sencillo en la propiedad project_name_lowecase se guardará el contenido transformado en minúsculas que venga en la propiedad project_name.
<!-- Guardamos el nombre proyecto en minusculas--> <stringutil string="${project_name}" property="project_name_lowercase"> <lowercase/> </stringutil>
domingo, 27 de mayo de 2012
ANT: Conversión de la fecha del sistema a String con formato.
Prerequisitos: Conocimientos básicos de apache ANT (instalación y uso)
Partiendo de la base que ya tenemos los conocimentos básicos de como instalar y usar apache ant, vamos a ver como conseguir imprimir una fecha con el formato 20120412190755.
El objetivo de esta investigación ha sido para utilizar este formato de fecha como nombre de un archivo JAR que se genera cada cierto tiempo. De este modo conseguimos un nombre siempre diferente para el archivo.
La manera de conseguir esto es con la tarea de ANT tsamp que permite recuperar la fecha del sistema y darle el formato deseado.
Para darle formato utilizarmos la propiedad pattern y los formatos disponibles lo podemos formar como queramos en base a estas opciones:
Letter | Date or Time Component | Presentation | Examples |
---|---|---|---|
G
| Era designator | Text | AD
|
y
| Year | Year | 1996 ; 96
|
M
| Month in year | Month | July ; Jul ; 07
|
w
| Week in year | Number | 27
|
W
| Week in month | Number | 2
|
D
| Day in year | Number | 189
|
d
| Day in month | Number | 10
|
F
| Day of week in month | Number | 2
|
E
| Day in week | Text | Tuesday ; Tue
|
a
| Am/pm marker | Text | PM
|
H
| Hour in day (0-23) | Number | 0
|
k
| Hour in day (1-24) | Number | 24
|
K
| Hour in am/pm (0-11) | Number | 0
|
h
| Hour in am/pm (1-12) | Number | 12
|
m
| Minute in hour | Number | 30
|
s
| Second in minute | Number | 55
|
S
| Millisecond | Number | 978
|
z
| Time zone | General time zone | Pacific Standard Time ; PST ; GMT-08:00
|
Z
| Time zone | RFC 822 time zone | -0800 |
Aquí os pongo el código que genera la fecha actual en formato [añomesdiahoraminutosysegundos]
<project basedir="." default="run" name="test"> <target name="run"> <tstamp> <format pattern="yyyyMMdHHmmss" property="VERSION"> </format> </tstamp> <echo message="${VERSION}"> </echo></target> </project>
Referencias:
Documentación de tstamp
Ejemplo de uso para nombrar un archivo
jueves, 17 de mayo de 2012
Flex 4: Acceder al contenedor padre de un Itemrenderer
Calling parent container from ItemRendere.
Pre-requisitos: Conocimientos básicos de Flex 4 (funcionamiento de un Itemrenderer) y Action Script 3.
Una de las mejores características de flex es que te permite crear listas de objetos, con la particularidad de que podemos crear diseños e interfaces muy visuales de estos objetos gracias a los Itemrederers. Por ejemplo, una lista botones donde cada botón tiene un diseño similar con funcionalidad similar.
Pero puede que tengamos la necesidad de acceder, no sólo a la lista que contiene al itemrenderer sino también a la vista que contiene a esta lista para acceder a alguno de sus objetos declarados o funciones.
La parte negativa de esto es que el Itemrenderer que lo utilice quedará totalmente acoplado a la vista padre a la que hacemos referencia y no podrá ser un elemento independiente y reutilizable por otras listas.
El propio itemrenderer ya nos trae distintas propiedades rellenas con la información de los datos con lo que hemos rellenado la lista.
data: Contiene la información del elemento de la lista al que representa el itemrenderer.
parentDocument: hace referencia a algún objetos padre que contiene al itemrederer.
También se puede sobre-escribir funciones como set data() que se ejecutará para de asignar el valor de uno de los elementos de la lista al itemrenderer.
Para acceder a la vista padre lo que debemos utilizar es parentDocument.parentDocument que nos devolverá un objeto del tipo de contiene a lista.
El ejemplo que os pongo a continuación es una mxml principal(MainApp.mxml) con una lista y el itemrender utilizado (ServiceIR.mxml). Se supone que ambos están en el mismo paquete de la aplicación.
MainApp.mxml
El objeto items del data provider podría ser un arrayCollections de Strings por ejemplo.
ServicesIR.mxml
Utilizo la función set data para asignar para recuperar al objeto padre y acceder a lo que necesite para modificar los datos como sea necesario.
Pre-requisitos: Conocimientos básicos de Flex 4 (funcionamiento de un Itemrenderer) y Action Script 3.
Una de las mejores características de flex es que te permite crear listas de objetos, con la particularidad de que podemos crear diseños e interfaces muy visuales de estos objetos gracias a los Itemrederers. Por ejemplo, una lista botones donde cada botón tiene un diseño similar con funcionalidad similar.
Pero puede que tengamos la necesidad de acceder, no sólo a la lista que contiene al itemrenderer sino también a la vista que contiene a esta lista para acceder a alguno de sus objetos declarados o funciones.
La parte negativa de esto es que el Itemrenderer que lo utilice quedará totalmente acoplado a la vista padre a la que hacemos referencia y no podrá ser un elemento independiente y reutilizable por otras listas.
El propio itemrenderer ya nos trae distintas propiedades rellenas con la información de los datos con lo que hemos rellenado la lista.
data: Contiene la información del elemento de la lista al que representa el itemrenderer.
parentDocument: hace referencia a algún objetos padre que contiene al itemrederer.
También se puede sobre-escribir funciones como set data() que se ejecutará para de asignar el valor de uno de los elementos de la lista al itemrenderer.
Para acceder a la vista padre lo que debemos utilizar es parentDocument.parentDocument que nos devolverá un objeto del tipo de contiene a lista.
El ejemplo que os pongo a continuación es una mxml principal(MainApp.mxml) con una lista y el itemrender utilizado (ServiceIR.mxml). Se supone que ambos están en el mismo paquete de la aplicación.
MainApp.mxml
<s:Application
................
<s:Group width="100%">
<s:HGroup left="40" top="40">
<s:List width="100%" dataProvider="{items}"
itemRenderer="ServicesIR"
contentBackgroundColor="#E6E7E8" borderVisible="false">
<s:layout>
<s:HorizontalLayout columnWidth="50" gap="5"/>
</s:layout>
</s:List>
.....
</Application>
El objeto items del data provider podría ser un arrayCollections de Strings por ejemplo.
ServicesIR.mxml
<?xml version="1.0" encoding="utf-8"?>
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx"
autoDrawBackground="true">
...
<fx:Script>
<![CDATA[
override public function set data(value:Object):void
{
var parent:MainApp = parentDocument.parentDocument; //Instance of MainApp.mxml
............................
}
]]>
</fx:Script>
..............
}
<s:ToggleButton id="tab" label="{data}" horizontalCenter="0" verticalCenter="0"/>
</s:ItemRenderer>
Utilizo la función set data para asignar para recuperar al objeto padre y acceder a lo que necesite para modificar los datos como sea necesario.
Etiquetas:
Action Script 3,
flex 4,
itemrenderer
Ubicación:
Madrid, España
Suscribirse a:
Entradas (Atom)