Translate

martes, 24 de diciembre de 2013

TOAD: Exportar e importar los datos de una tabla


Me encontraba haciendo una actualización de una tabla en TOAD y lo que más fácil me ha parecido para modificar una columna ha sido, copiar el script de creación, modificarlo en el editor de queries y lanzarlo para llevar a cabo esa modificación.




La modificación se ha hecho fácilmente y correctamente pero el problema ha sido que me he cargado todos los datos que había. Así que he aprendido la lección para la próxima y he aprendido lo que hay que hacer para salvarlos.

Lo mejor desde mi punto de vista es guardarlos en un archivo de texto, un archivo table.sql y tenerlos allí por si pasa algo.

Para ello hacemos los siguientes pasos:

1 - vamos a la pantalla de editor donde lanzamos las queries y hacemos un select sobre toda la tabla

2 - Una vez tenemos los resultados tenemos que fijarnos en el botón que hay encima de ellos que es Export dataset



3 - Elegimos las opciones de exportación, con el formato INSERT STATEMENTS, y selecionamos la ruta donde queremos que se exporten los datos.



Restauración de los datos:

Una vez que tenemos los datos para restaurarlos una manera simple es copiar y pegar en el editor ejecutar como si fuera un script pulsando en el rayo y se realizarán todos los inserts.



Y con estos pasos ya tendremos todos los datos de la tabla importados de nuevo














miércoles, 27 de noviembre de 2013

Gradle: configurar las dependencias transitivas de tu build.gradle

Title: Configure your transitive dependencies from your build.gradle

Del mismo modo que hicimos en su momento con un proyecto maven para eliminar sus dependencias transitivas. Ahora haremos lo mismo con un proyecto Gradle pero además aprenderemos a manejarlas un poco más en profundidad.

Nos basaremos en un proyecto Web con Spring Framework de modo que nuestro proyecto utilice el repositorio de Maven y recupere dependencias de Spring Framework.

Para ello en nuestro build.gradle del proyecto ponemos lo siguiente:

build.gradle
--
apply plugin: 'java'
apply plugin: 'war'

sourceCompatibility = 1.5
version = '1.0.0'
jar {
    manifest {
    attributes 'Implementation-Title': 'mySpringWebProject', 'Implementation-Version': version
    }
}

repositories {
    mavenCentral()
}

dependencies {
    compile ('org.springframework:spring-webmvc:3.2.5.RELEASE')
}

--
Con esto conseguimos que se importen todas las librerías que el proyecto web necesita y incluyendo las dependencias transitivas de las que depende nuestra librería spring-webmvc.





Si no queremos que todas las dependencias transitivas de las librerías que utilizamos se descarguen haremos lo siguiente:

Modo 1:


--
.....
......
dependencies {
     compile ('org.springframework:spring-webmvc:3.2.5.RELEASE'){transitive=false}
    
}
.....
.....
--

Modo 2:

--
....
....
dependencies {
    compile module ('org.springframework:spring-webmvc:3.2.5.RELEASE')
}
....
....
--
Con estas opciones obtenemos sólo la importación de la librería seleccionada.


La flexibilidad de Gradle nos da la posibilidad de seleccionar que dependencias transitivas queremos que se descarguen o no.

--
...
...
dependencies {
    compile module ('org.springframework:spring-webmvc:3.2.5.RELEASE'){
      dependency 'org.springframework:spring-beans:3.2.5.RELEASE'
    }

....
....
--

Pero tenemos que tener en cuenta que las dependencias transitivas de la propia dependencias también se intentarán descargar. Por lo tanto todo lo que dependa de  spring-beans también se descargará.

El resultado es el siguiente:


Ya que spring-core es dependencia spring-beans al igual que commons-logging

Para que sólo se descargara spring-beans tenemos que poner lo siguiente.

Modo 1:

--
...
...
dependencies {
    compile module ('org.springframework:spring-webmvc:3.2.5.RELEASE'){
      dependency ('org.springframework:spring-beans:3.2.5.RELEASE'){
           transitive=false
      }
    }
}

....
....

--
Modo 2:

--

...
...

dependencies {
    compile module ('org.springframework:spring-webmvc:3.2.5.RELEASE'){
      dependency module('org.springframework:spring-beans:3.2.5.RELEASE')    }
}
....
....
--

De esta manera conseguimos el resultado deseado


Si queremos descargar varias, dependencias, por ejemplo spring-beans y spring-core, haremos los siguiente

--

...
...
dependencies {
    compile module ('org.springframework:spring-webmvc:3.2.5.RELEASE'){
      dependencies module('org.springframework:spring-beans:3.2.5.RELEASE'), 
                   module('org.springframework:spring-core:3.2.5.RELEASE')   
      
      }
}

....
....
--
De este modo obtenemos:



Espero que con todos estos ejemplos te hayan servido para aprender a configurar tus dependencias en tu proyecto Gradle.

Se agradecen comentarios, críticas y recomendaciones.

Referencias:
Grade Dependency Management Bascis
Gradle Dependency Managemet

jueves, 24 de octubre de 2013

Scripts para MongoDB con Javascript y JSON: ejemplo práctico

Title: Scripts for MongoDB with Javascript and JSON.

En esta entrada quiero ilustrar como se hace un script de actualización de datos para MongoDB utilizando el lenguaje de programación javascript.

Los datos en MongoDB están almacenados en JSON y vamos ver como poblar una base de datos con unos cuantos objectos JSON y también como realizar unas sencillas manipulaciones de los objectos creados.

Toda la información que aquí os pongo es todo lo que necesitáis para empezar a lanzar scripts a cualquier base de datos MongoDB situada en cualquier host o ip.

Se da por hecho que la instalación de MongoDB ya está hecha, sino puedes consultar aquí como instalarlo en Windows 7 de una manera muy sencilla.

Los pasos para crear y lanzar nuestros scripts son los siguientes:

1 - Arrancar motor de MongoDB
2 - Abrir una ventana de comandos y situarnos en el directorio bin de mongo.
3 - Creación del script de poblado de base de datos
4 - Lanzamiento del script.
5 - Comprobación  de datos
6 - Creación de script de actualización
7 - Lanzamiento del script.
8 - Comprobación  de datos

Nota: Siempre tenemos que tener un MongoDB instalado en nuestra máquina local donde realizaremos las operaciones de lanzamiento del script, pero esté script podrá ejecutar en cualquier instalación de MongoDB que tengas en remoto siempre que conozcas su host y puerto.


1 - Arrancar motor de MongoDB

Lo arrancamos yendo a la ruta de instalación de MongoDB y ejecutando: mongod --dbpath ..\data\db

[MONGODB-PATH]\bin\mongod --dbpath ..\data\db




2 - Abrir una ventana de comandos y situarnos en el directorio bin de mongo

En windows sería:

cmd
cd [MONGODB-PATH]\bin



3 - Creación del script de poblado de base de datos

Con nuestro editor favorito creamos un script en lenguaje javascript para ejecutarlo en la instancia de MongoDB que queramos.

Los aspectos importes que tenemos que tener en cuenta son los siguientes que se entenderán perfectamente al ver el código:

  • Tendremos que tener creada ya, una base de datos con su nombre. Si no la tenemos creada no pasa nada porque al utilizarla por primera vez e insertar en ella se creará.          
  •  En el propio script elegimos  el host o direccion ip del mongodb donde se ejecutará este script y la base de datos donde se aplicará. Es decir que es en el propio script donde indica el destino de todo.
  • Al ser MongoDb una base de datos NoSQL no es necesario crear una estructura de datos previa directamente iremos insertando nuestros datos con código javascript y estructura JSON.
  • El ID de los registros prefiero introducirlo yo manualmente porque si dejamos que el propio Mongodb nos lo autogenere no lo hace como un número entero normal y a la hora de buscarlo desde una aplicación puede resultar complicado. Así que recomiendo generar los ID de los registros en el servidor con un generador de ids único y añadirlo a tus registros, otra opción es generar el código con una función en javascript dentro del propio script.


El script de relleno de la base de datos es el siguiente:



--

/*
 * Script que se encarga de poblar la base de datos  
 * 
 */

print("STARTING SCRIPT");
//Host donde está nuestra base de datos, no tiene que ser nuestro equipo local, puede ser cualquier mongoDb.
conn = new Mongo("localhost");
//Nombre de la base de datos que vamos a utilizar
db = conn.getDB("antuandb");

/*Limpiamos la base de datos por si existia algo antes*/
db.dropDatabase();


/*coleciones de nuestro modelo de datos*/
db.createCollection("users");
db.createCollection("courses");

/* Usuarios */
print("***********creating users*********");


user1 = {
  
"_id" : "0",
"name" : "Antuan",
"surname" : "Martín",
"age": 35,
"deleted":false

}

user2 = {
  
"_id" : "1",
"name" : "Felime",
"surname" : "Rodriguez",
"age": 31,
"deleted":false

}


user3 = {
  
"_id" : "2",
"name" : "Jose",
"surname" : "Carrizo",
"age": 28,
"deleted":false

}


print("***********creating courses*********");

/* courses */


course1 = {
     
    "_id" : "0",
    "students" : [],
    "tutors" : [],
    "name":"Master en Animación y Modelado 3d con Maya en Madrid",
    "credits":3.5,
    "hours":35
  
};

course2 = {
   
    "_id" : "1",
    "students" : [],
    "tutors" : [],
    "name":"SEO: Posicionamiento Web en Buscadores",
    "credits":4.0,
    "hours":40
  
};

course3 = {
   
    "_id" : "2",
    "students" : [],
    "tutors" : [],
    "name":"Máster en Game design",
    "credits":2.8,
    "hours":28  
};


print("***********saving users*********");
db.users.save(user1);
db.users.save(user2);
db.users.save(user3);

print("***********saving courses*********");
db.courses.save(course1);
db.courses.save(course2);
db.courses.save(course3);


print("SCRIPT FINISHED");

--

4 - Lanzamiento del script.

Ya tenemos el script guardado en un archivo por ejemplo llamado initDB.js y estamos situados en el directorio [MONGODB-PATH]\bin como indicamos en el apartado 2.

Para larzar el script ejecutamos el siguiente comando.

mongo archivo1.js [archivon.js]

en nuestro caso

mongo initDB.js

Nota: Podemos poner tantos archivos .js como utilicemos, o sea que se pueden dividir los scripts en varios archivos.


Si tenemos algún error durante la ejecución podemos verlo en la salida de la ventana de comandos, tras la ejecución del script, donde nos dirá el error cometido y la línea en la que se ha producido, en este caso la línea 71 y nos se ha producido un SyntaxError.

--

MongoDB shell version: 2.4.1
connecting to: test
Mon Oct 21 18:12:09.559 JavaScript execution failed: SyntaxError: 
Unexpected string at C:\......\initDB.js:L71
failed to load: C:\..............\initDB.js

--


Una vez ejecutado el script correctamente obtengo la siguiente salida.

--
C:\mongodb-win32-2.4.1\bin>mongo initDB.js
MongoDB shell version: 2.4.1
connecting to: test
STARTING SCRIPT
***********creating users*********
***********creating courses*********
***********saving users*********
***********saving courses*********
SCRIPT FINISHED

--

No hay que hacer caso de lo del mensaje:

connecting to: test

porque es la base de datos de conexión por defecto.



5 - Comprobación  de datos

Yo recomiendo siempre que ejecutes un script comprobar los datos que se han introducido en la base de datos sean correctos tanto en número de registros como en los tipos de datos, porque podemos llevarnos sorpresas y quizás lo que era un Double es un String o lo que debia de ser un Array es un String y eso es un error grave.

Con el software MongoVUE que ya os he recomendado podemos ver esto sin problemas.

NOTA: No os fieis nunca del modo texto porque no deja de ser una interpretación del JSON, yo siempre me voy a la vista en arbol para comprobar los tipos de datos de cada campo (String, Double, Arry, etc..).



Si no te has descargado MongoVE, lo cual es un error muy grande, tienes la opción de ver los resultados por consola, para ello ejecutamos lo siguiente en una ventana de comandos:

mongo

y entramos en la shell de mongo, donde podremos operar con la base de datos realizar las siguiente operaciones, una para usar la base de datos que nos hace falta y la segunda para realizar la query de consulta de los datos.

> use antuandb
> db.users.find()

Y podremos ver el resultado en pantalla pero queda muy feo y no podemos ver bien los tipos de datos.






6 - Creación de script de actualización

Una vez que hemos creado un script de llenado de la base de datos ahora vamos a hacer un script de actualización de los datos que tenemos.

Vamos a hacer dos modificaciones sobre los datos para que podamos ver varios ejemplos de actualización.

  • Primero: vamos añadir un campo nuevo a todos los cursos que es deleted=false y sumaremos una hora al campo hours.
  • Segundo: vamos agregar a los usuarios menores de 30 a los cursos como alumnos y a los mayores de 30 como tutor.

Cosas importantes a tener en cuenta:

  • Al realizar una query los datos se almacenan una variable de tipo cursor que podemos recorrer y a su vez nos darán funciones interesantes como count() o forEach(funciton).
  • En la query donde buscamos los cursos debemos de utilizar la función snapshot porque si no la usamos al realizar modificaciones sobre los propios objetos que están en el cursos de resultados este se podría ver alterado. Usando snapshot garantizamos que los datos recuperados en ese cursos no se alterarán.
  •  La manera de recorrer los datos es usando la función forEach que incluirá una función para procesar cada unos de los datos del cursor.
  • lo la función addToSet introducimos un valor en un array del objeto de MongoDB de tal modo que si el objeto ya existe este no se inserta 2 veces. Esto lo hacemos para introducir el id del usuario en el array de alumnos o de tutores del curso.



--
/*
 * Script que se encarga de actualizar la base de datos  
 * 
 */

print("STARTING SCRIPT");
//Host donde está nuestra base de datos, no tiene que ser nuestro equipo local, puede ser cualquier mongoDb.
conn = new Mongo("localhost");
//Nombre de la base de datos que vamos a utilizar
db = conn.getDB("antuandb");

var i_int = 0;
var modificados_int = 0;
var ignorados_int = 0;
var erroneos_int = 0;

//Recuperamos todos los cursos
var courses_cur = db.courses.find().snapshot();
var totalSize_int = courses_cur.count();

print("******FIRST PART UPDATING COURSES************");

courses_cur.forEach(function(course){
 i_int++;
 print("*********************************");
    print("RECORD "+i_int +" of " + totalSize_int);   
 print("PROCESSING:"+ course.name + "("+course._id+")");
 
 //añado la nueva propiedad
 course.deleted = false;
 
 //Modifico propiedad existente
 course.hours = course.hours + 1;
   
 db.courses.save(course);
 
 print("UPDATED");
});

print("******END FIRST PART************");

print("******SECOND PART ADDING STUDENTS AND TUTORS************");

//Recorro todos los cursos
courses_cur = db.courses.find().snapshot();
courses_cur.forEach(function(course){
   print("*********************************");
   print("PROCESSING COURSE:"+ course.name + "("+course._id+")");
   var id_course = course._id;
   
   //Recupero los usario mayores de 30 años
   var users_cur = db.users.find({age:{$gt:30}}).snapshot();
         
   users_cur.forEach(function(user){
    
    print("      PROCESSING USER:"+ user.name + "("+user._id+")");
    var id_user = user._id;    
    db.courses.update({_id:id_course},{$addToSet:{"students":id_user}});
    
    print("      USER ADDED AS STUDENT");
 
   });
   
   //Recupero los usuarios menores de 30 años
   var users_cur = db.users.find({age:{$lte:30}}).snapshot();
   users_cur.forEach(function(user){
    
    
    print("      PROCESSING USER:"+ user.name + "("+user._id+")");
    var id_user = user._id;    
    db.courses.update({_id:id_course},{$addToSet:{"tutors":id_user}});
    
    print("      USER ADDED AS TUTOR");
    
   });      
 
});




--



7 - Lanzamiento del script.

Una vez guardado el script en el archivo updateDB.js lo ejecutamos igual que hicimos en el paso 4

mongo updateDB.js

La salida es la siguiente




--
C:\mongodb-win32-2.4.1\bin>mongo updateDB.js
MongoDB shell version: 2.4.1
connecting to: test
STARTING SCRIPT
******FIRST PART UPDATING COURSES************
*********************************
RECORD 1 of 3
PROCESSING:Master en Animación y Modelado 3d con Maya en Madrid(0)
UPDATED
*********************************
RECORD 2 of 3
PROCESSING:SEO: Posicionamiento Web en Buscadores(1)
UPDATED
*********************************
RECORD 3 of 3
PROCESSING:Máster en Game design(2)
UPDATED
******END FIRST PART************
******SECOND PART ADDING STUDENTS AND TUTORS************
*********************************
PROCESSING COURSE:Master en Animación y Modelado 3d con Maya en Madrid(0)
      PROCESSING USER:Antuan(0)
      USER ADDED AS STUDENT
      PROCESSING USER:Felipe(1)
      USER ADDED AS STUDENT
      PROCESSING USER:Jose(2)
      USER ADDED AS TUTOR
*********************************
PROCESSING COURSE:SEO: Posicionamiento Web en Buscadores(1)
      PROCESSING USER:Antuan(0)
      USER ADDED AS STUDENT
      PROCESSING USER:Felipe(1)
      USER ADDED AS STUDENT
      PROCESSING USER:Jose(2)
      USER ADDED AS TUTOR
*********************************
PROCESSING COURSE:Máster en Game design(2)
      PROCESSING USER:Antuan(0)
      USER ADDED AS STUDENT
      PROCESSING USER:Felipe(1)
      USER ADDED AS STUDENT
      PROCESSING USER:Jose(2)
      USER ADDED AS TUTOR
SCRIPT FINISHED

--


8 - Comprobación  de datos

Finalmente realizamos la comprobación de que que los datos se han usertado correctamente, recomiendo hacerlo porque MongoDB no da errores si la inserción no es correcta o te equivocas en una query, directamente seguirá ejecutando el código como nada hubiera pasado.

echando un ojo a los datos vemos que todo está correcto y ya está todo terminado.



--

{
  "_id" : "0",
  "credits" : 3.5,
  "deleted" : false,
  "hours" : 41.0,
  "name" : "Master en Animación y Modelado 3d con Maya en Madrid",
  "students" : ["0", "1"],
  "tutors" : ["2"]
}

{
  "_id" : "0",
  "name" : "Antuan",
  "surname" : "Martín",
  "age" : 35.0,
  "deleted" : false
}

--


Espero que os resulte muy útil y si es así se agradece un comentario. También se aceptan críticas y mejoras de mismo, así como dudas.

Referencias:

Write Scripts for the mongoDb Shell




miércoles, 11 de septiembre de 2013

Error usando Junit combinado con AspectJ: AspectJAdviceParameterNameDiscoverer$AmbiguousBindingException

En nuestro proyecto J2EE hemos utilizado AspectJ para capturas las excepciones que se producen en la parte servidora en JAVA.

Es muy cómodo porque no tienes que poner bloques try....catch en todos los servicios de la aplicación para aplicar la gestión que quieras a las excepciones, de este modo tienes toda la gestión de las excepciones en un solo punto.

El problema lo tenemos a la hora de hacer los test unitarios y de integración con JUNIT ya que no se lleva nada bien el tema de que los servicios sobre los que hacemos los test. Los casos de uso que tenemos son los siguientes:

1 - Creación y ejecución de los test en Eclipse. En este caso los test pasan correctamente



2 - Ejecución de los test en Jenkins a través de un scripts (maven o ant) de compilación y ejecución de los test.

En este caso es donde nos encontramos con el problema de que la solución de la utilización de Aspecj para la gestión de excepciones no funciona porque nos devuelve el siguiente error.


--

java.lang.IllegalStateException: Failed to load ApplicationContext
 at org.springframework.test.context.TestContext.getApplicationContext(TestContext.java:157)
 at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.injectDependencies(DependencyInjectionTestExecutionListener.java:109)
 at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.prepareTestInstance(DependencyInjectionTestExecutionListener.java:75)
 at org.springframework.test.context.TestContextManager.prepareTestInstance(TestContextManager.java:321)
 at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.createTest(SpringJUnit4ClassRunner.java:211)
 at org.springframework.test.context.junit4.SpringJUnit4ClassRunner$1.runReflectiveCall(SpringJUnit4ClassRunner.java:288)
 at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.methodBlock(SpringJUnit4ClassRunner.java:290)
 at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:231)
 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.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:174)
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'org.springframework.data.repository.core.support.RepositoryInterfaceAwareBeanPostProcessor#0': BeanPostProcessor before instantiation of bean failed; nested exception is org.springframework.aop.aspectj.AspectJAdviceParameterNameDiscoverer$AmbiguousBindingException: Still 2 unbound args at this(),target(),args() binding stage, with no way to determine between them
 at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:452)
 at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:294)
 at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:225)
 at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:291)
 at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197)
 at org.springframework.context.support.AbstractApplicationContext.registerBeanPostProcessors(AbstractApplicationContext.java:740)
 at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:449)
 at org.springframework.test.context.support.AbstractGenericContextLoader.loadContext(AbstractGenericContextLoader.java:103)
 at org.springframework.test.context.support.AbstractGenericContextLoader.loadContext(AbstractGenericContextLoader.java:1)
 at org.springframework.test.context.support.DelegatingSmartContextLoader.loadContext(DelegatingSmartContextLoader.java:228)
 at org.springframework.test.context.TestContext.loadApplicationContext(TestContext.java:124)
 at org.springframework.test.context.TestContext.getApplicationContext(TestContext.java:148)
Caused by: org.springframework.aop.aspectj.AspectJAdviceParameterNameDiscoverer$AmbiguousBindingException: Still 2 unbound args at this(),target(),args() binding stage, with no way to determine between them
 at org.springframework.aop.aspectj.AspectJAdviceParameterNameDiscoverer.maybeBindThisOrTargetOrArgsFromPointcutExpression(AspectJAdviceParameterNameDiscoverer.java:519)
 at org.springframework.aop.aspectj.AspectJAdviceParameterNameDiscoverer.getParameterNames(AspectJAdviceParameterNameDiscoverer.java:264)
 at org.springframework.core.PrioritizedParameterNameDiscoverer.getParameterNames(PrioritizedParameterNameDiscoverer.java:54)
 at org.springframework.aop.aspectj.AbstractAspectJAdvice.bindArgumentsByName(AbstractAspectJAdvice.java:420)
 at org.springframework.aop.aspectj.AbstractAspectJAdvice.calculateArgumentBindings(AbstractAspectJAdvice.java:375)
 at org.springframework.aop.aspectj.annotation.ReflectiveAspectJAdvisorFactory.getAdvice(ReflectiveAspectJAdvisorFactory.java:218)
 at org.springframework.aop.aspectj.annotation.InstantiationModelAwarePointcutAdvisorImpl.instantiateAdvice(InstantiationModelAwarePointcutAdvisorImpl.java:140)
 at org.springframework.aop.aspectj.annotation.InstantiationModelAwarePointcutAdvisorImpl.<init>(InstantiationModelAwarePointcutAdvisorImpl.java:89)
 at org.springframework.aop.aspectj.annotation.ReflectiveAspectJAdvisorFactory.getAdvisor(ReflectiveAspectJAdvisorFactory.java:134)
 at org.springframework.aop.aspectj.annotation.ReflectiveAspectJAdvisorFactory$1.doWith(ReflectiveAspectJAdvisorFactory.java:74)
 at org.springframework.util.ReflectionUtils.doWithMethods(ReflectionUtils.java:473)
 at org.springframework.util.ReflectionUtils.doWithMethods(ReflectionUtils.java:451)
 at org.springframework.aop.aspectj.annotation.ReflectiveAspectJAdvisorFactory.getAdvisors(ReflectiveAspectJAdvisorFactory.java:70)
 at org.springframework.aop.aspectj.annotation.BeanFactoryAspectJAdvisorsBuilder.buildAspectJAdvisors(BeanFactoryAspectJAdvisorsBuilder.java:109)
 at org.springframework.aop.aspectj.annotation.AnnotationAwareAspectJAutoProxyCreator.findCandidateAdvisors(AnnotationAwareAspectJAutoProxyCreator.java:86)
 at org.springframework.aop.aspectj.autoproxy.AspectJAwareAdvisorAutoProxyCreator.shouldSkip(AspectJAwareAdvisorAutoProxyCreator.java:107)
 at org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator.postProcessBeforeInstantiation(AbstractAutoProxyCreator.java:278)
 at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyBeanPostProcessorsBeforeInstantiation(AbstractAutowireCapableBeanFactory.java:880)
 at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.resolveBeforeInstantiation(AbstractAutowireCapableBeanFactory.java:852)
 at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:446)


--

La solución a este problema consiste en añadir un parámetro en la compilación de las clases en el script que se encarga de compilar las clases. El parámetro añadir es el siguiente: -g:vars

Os pongo el ejemplo de como lo añado en mi script donde todas mis clases están en las carpetas src y javatest

--
<path id="lib.path.ref">
      <fileset dir="../WebContent/WEB-INF/lib" includes="*.jar"/>
   <fileset dir="./libs" includes="*.jar"/>
</path>
<javac srcdir="../src:../javatest"
          destdir="${DirectorioBase}/WEB-INF/classes"
          classpathref="lib.path.ref"
          debug="off"
          source="1.7"
          optimize="true"
          target="1.7"
          fork="true"
   encoding="UTF8"
          includeantruntime="true">
    
                 <compilerarg value="-g:vars"/>  <!--Argumento especial para la compilación de AspectJ -->
</javac>
--

Con esto el error desaparece completamente.

Referencias:

Referencia 1 - SpringSource

Referencia 2 - epubbud





martes, 30 de julio de 2013

Eclipse: Refrescar un proyecto desde ANT

Yo realizo muchos scripts en ant, desde lo encargados de instalar, empaquetar y desplegar los proyectos hasta los que se encargan de inter-conectar proyectos del entorno de desarrollo (eclpise en este caso) como puede ser copia de archivos a otros proyectos y refresco de los mismos.

El refresco de un proyecto siempre se necesario siempre que se copian archivos desde otra ubicación, por ejemplo nosotros estamos utilizando proyectos Flex que tiene módulos, entonces estos módulos cada vez que se compilan quiero que se copien en el proyecto principal para su ejecución. Una vez copiado el archivo con el script de Ant lo que es necesario es refrescar el proyecto para que este se entere de que tiene archivos nuevos.

Esta funcionalidad puede hacer se directamente con un script de ant (ej: build.xml) que contenga la siguiente instrucción:

<eclipse.refreshLocal resource="project_name/folder_name" depth="infinite" />

Donde resource es la ruta relativa desde donde está nuestro archivo ant al proyecto que quieres refrescar.

Ejemplo: Script que se encarga de copiar todos los SWF situados en bin-debug del proyecto actual a la carpeta ../modules del proyecto AntuanMainProject.

Una vez copiado realizo el refresco del proyecto para que se materialice la modificación.

<?xml version="1.0" encoding="UTF-8"?>
   <project name="ForumModule" basedir="." default="copySWF" xmlns:artifact="antlib:org.apache.maven.artifact.ant">
   
      <target name ="copySWF" description="Copy SWF Module to Projects">             
       <copy todir="../../AntuanMainProject/bin-debug/modules" overwrite="true"><fileset dir="../bin-debug/"><include name="**/*.swf"/></fileset></copy>                     
       
       <eclipse.refreshLocal resource="../../AntuanMainProject/" depth="infinite"></eclipse.refreshLocal>
      </target>
            
</project>



lunes, 1 de julio de 2013

Instalar Tomcat como servicio de Windows 7

Para instalar Apache Tomcat como servicio de windows es tan fácil como:

1 - Descargar la última versión de Apache Tomcat (Yo prefiero en zip nada de instaladores).
2 - Descomprimir/Instalar el archivo descargado.
3 - Abrir una consola (cmd.exe) de commandos con permisos de administrador e ir al directorio de instalación del Tomcat.


5 - Creamos las siguientes variables de entorno con la rutas de instalación de nuestro Tomcat y de la máquina virtual de Java.

Nota: Damos por supuesto que Java está instalado en el siguiente directorio: C:\Program Files\Java\jdk1.7.0_09


CATALINA_HOME:  "C:\apache-tomcat-7.0.33-src-A"
JAVA_HOME:        "C:\Program Files\Java\jdk1.7.0_09"

6 - Entrar en el directorio bin y ejecutar el comando: service install Tomcat7



Tomcat 7 es el nombre que le daremos al servicio y es importante porque es el que nos servirá para arrancarlo.

Podemos eliminarlo con:

service remove Tomcat7

7 - Comprobar que el servicio se ha instalado correctamente entrando en las herramientas administrativas servicios



Y ya podemos arrancarlo y pararlo desde los servicios o desde linea de comando con las instrucciones

net start Tomcat7
net stop Tomcat7


Arrancar el servicio de tomcat desde linea de comando nos permitirá entre otras cosa arrancarlo fácilmente desde un script de ant.

Problemas conocidos:

1 - Problemas con la instalación del servicio:



Failed installing 'Tomcat7' service

Solución:
Este problema se produce principalmente porque no tenemos permisos desde la consola para instalar servicios, debemos de asegurarnos que tenemos permisos de administrador.


2 - Problema la arrancar el servicio:

Al arrancar el servicio desde la ventana de Herramientas del sistema - Servicios recibimos el siguiente mensaje:



O desde la consola de comando:

Error específico del servicio: 0.




Si vemos la consola de tomcat que está en el directorio /logs concretamente en el archivo comons-daemon2013-07-01.log veremos el siguiente error:

[2013-07-01 13:33:25] [info]  Starting service...
[2013-07-01 13:33:25] [error] %1 no es una aplicación Win32 válida.
[2013-07-01 13:33:25] [error] Failed creating java C:\Program Files\Java\jdk1.7.0_09\jre\bin\server\jvm.dll
[2013-07-01 13:33:25] [error] %1 no es una aplicación Win32 válida.
[2013-07-01 13:33:25] [error] ServiceStart returned 1
[2013-07-01 13:33:25] [error] %1 no es una aplicación Win32 válida.
[2013-07-01 13:33:25] [info]  Run service finished.
[2013-07-01 13:33:25] [info]  Commons Daemon procrun finished


Solución1: El problema se soluciona editando el script service.bat que se encaga de la instalación del servicio que está en el directorio /bin. Hacemos una copia de seguridad por si acaso del archivo y lo abrimos y buscamos todas las apariciones de "server\jvm.dll" y la cambiamos por "client\jvm.dll". 

Guardamos y reinstalamos el servicio de nuevo y veremos como arranca perfectamente.

Solución2:  Vamos al directorio bin de la instalación de nuestro tomcat y ejecutamos el archivo tomcat7w.exe que nos permite retocar el servicio que hemos creado a través del script.



Y cambiamos la ruta para que utilice el client\jvm.dll



3 - Problema con la versión de java con la que se arranca el servicio

Al arrancar el servicio y desplegar alguna de las aplicaciones puede que nos de el siguiente error:

ADVERTENCIA: Unable to load class [xxx.xxx.xxx.xxx.MainDashboardController] to check against the @HandlesTypes annotation of one or more ServletContentInitializers.

java.lang.UnsupportedClassVersionError: com/xxxx/xxxx/xxx/MainDashboardController: Unsupported major.minor version 51.0 (no puedo cargar clase com.gniux.dashboard.mvc.MainDashboardController)

 at org.apache.catalina.loader.WebappClassLoader.findClassInternal(WebappClassLoader.java:2822)

 at org.apache.catalina.loader.WebappClassLoader.findClass(WebappClassLoader.java:1148)

 at org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1643)

 at org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1521)

 at org.apache.catalina.startup.ContextConfig.checkHandlesTypes(ContextConfig.java:1956)

 at org.apache.catalina.startup.ContextConfig.processAnnotationsStream(ContextConfig.java:1919)


Este problema se produce porque al crearse el servicio se ha creado utilizando una JRE de una versión más baja que la que ha compilado las clases de la aplicación.

Solución:
En mi caso yo tengo compilada mi aplicación con una JDK1.70_02 y para comprobar como se ha creado el servicio vamos al directorio bin de la instalación de nuestro tomcat y ejecutamos el archivo tomcat7w.exe que nos permite retocar el servicio que hemos creado a través del script.




Como vemos en la imagen el tomcat se está arrancando con un JRE6 lo modificamos poniendo la jvm.dll correcta de nuestra jdk en mi caso .....\Java\jdk1.7.0_02\jre\bin\client\jvm.dll

Simplemente cambiándolo arrancará sin problemas de versiones.


4 - Problemas de Memoria al arrancar el servicio

Al desplegar una aplicación lo más normal es que tengamos el siguiente problema de memoria y necesitemos retocar los parámetros memoria del servicio.

Información: Despliegue del archivo MyWeb.war de la aplicación web
java.lang.OutOfMemoryError: PermGen space
 at java.lang.ClassLoader.defineClass1(Native Method)
 at java.lang.ClassLoader.defineClass(ClassLoader.java:791)
 at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:142)
 at org.apache.catalina.loader.WebappClassLoader.findClassInternal(WebappClassLoader.java:2818)
 at org.apache.catalina.loader.WebappClassLoader.findClass(WebappClassLoader.java:1148)
 at org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1643)
 at org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1521)
 at org.apache.catalina.startup.ContextConfig.checkHandlesTypes(ContextConfig.java:1956)
 at org.apache.catalina.startup.ContextConfig.processAnnotationsStream(ContextConfig.java:1919)
 at org.apache.catalina.startup.ContextConfig.processAnnotationsJar(ContextConfig.java:1806)
 at org.apache.catalina.startup.ContextConfig.processAnnotationsUrl(ContextConfig.java:1765)
 at org.apache.catalina.startup.ContextConfig.processAnnotations(ContextConfig.java:1751)
 at org.apache.catalina.startup.ContextConfig.webConfig(ContextConfig.java:1255)
 at org.apache.catalina.startup.ContextConfig.configureStart(ContextConfig.java:882)
 at org.apache.catalina.startup.ContextConfig.lifecycleEvent(ContextConfig.java:317)
 at org.apache.catalina.util.LifecycleSupport.fireLifecycleEvent(LifecycleSupport.java:119)
 at org.apache.catalina.util.LifecycleBase.fireLifecycleEvent(LifecycleBase.java:89)
 at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5081)
 at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:145)
 at org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:812)
 at org.apache.catalina.core.ContainerBase.addChild(ContainerBase.java:787)
 at org.apache.catalina.core.StandardHost.addChild(StandardHost.java:607)
 at org.apache.catalina.startup.HostConfig.deployWAR(HostConfig.java:932)
 at org.apache.catalina.startup.HostConfig.deployWARs(HostConfig.java:723)
 at org.apache.catalina.startup.HostConfig.deployApps(HostConfig.java:470)
 at org.apache.catalina.startup.HostConfig.start(HostConfig.java:1322)
 at org.apache.catalina.startup.HostConfig.lifecycleEvent(HostConfig.java:311)
 at org.apache.catalina.util.LifecycleSupport.fireLifecycleEvent(LifecycleSupport.java:119)
 at org.apache.catalina.util.LifecycleBase.fireLifecycleEvent(LifecycleBase.java:89)
 at org.apache.catalina.util.LifecycleBase.setStateInternal(LifecycleBase.java:379)
 at org.apache.catalina.util.LifecycleBase.setState(LifecycleBase.java:324)
 at org.apache.catalina.core.ContainerBase.startInternal(ContainerBase.java:1041)
Exception in thread "Thread-1" java.lang.OutOfMemoryError: PermGen space
 at java.util.WeakHashMap$Values.iterator(WeakHashMap.java:897)
 at org.apache.juli.ClassLoaderLogManager.shutdown(ClassLoaderLogManager.java:324)
 at org.apache.juli.ClassLoaderLogManager$Cleaner.run(ClassLoaderLogManager.java:54)


Si vemos la guía de Apache tomcat de como instalat tomcat como servicio de Windows, vemos que en la creación del servicio se pueden definir los parámetros y variables del entorno en que se ejecutará el servicio.

Nota Importante: Es importante saber que al arrancar tomcat desde los servicios las variables de entorno no sirven para nada, todo tiene que estar configurado dentro de el servicio.

Solución: Vamos al directorio bin de la instalación de nuestro tomcat y ejecutamos el archivo tomcat7w.exe que nos permite retocar el servicio que hemos creado a través del script.



y vemos que por defecto ya tenemos unos parámetros de memoria añadidos Initial Memory Pool y Maximum Memory Pool,

Para arrancar un par de aplicaciones desde linea de commandos en tomcat yo pongo estos parámetros en el script de arrranque:

set CATALINA_HOME=C:\apache-tomcat-7.0.33-src-A

set JAVA_HOME=D:\antuan\Java\jdk1.7.0_02

set JAVA_OPTS=-Xms800m -Xmx800m -XX:MaxPermSize=256m 

Eso valores de Xms y Xmx se corresponden con Initial Memory Pool y Maximum Memory Pool y podemos modificarlos directamente sin problemas pero que pasa con MaxPermSize.

Para definir este valor devemos ponerlo dentro de las JavaOptions

-XX:MaxPermSize=256m



Aquí debes ajustar tus parámetros de memoria dependiendo de tu aplicación/es y arrancará correctamente.


Referencias:
Tomcat Error – Prunsrv.C Failed Creating Java (Jvm.Dll)
Windows-service-HowTo
Tomcat Service On Windows














viernes, 14 de junio de 2013

MongoDB: Hacer una query sobre campos del propio documento

La problemática de hoy surge porque me he visto en la necesidad de ver si dos campos de un mismo documento de mongoDb son iguales.

Para ello lo que necesito es hacer una query buscando el contenido de uno de los campos del documento en otro.

En mi caso tengo que recuperar los documentos de la tabla de usuarios donde el username sea igual a email de contacto.

{
  "_id" : "6006491b-04cc-45be-82cb-5612395d2d10",
  "username" : "xxxx@xxx.com",
  "password" : "xxxxxxx",
  "name" : "Manuel",
  "surname" : "Roberto Del Pino",
  "email" : "xxxx@xxx.com",
  "dni" : "",
  "phone" : "",
  "creationDate" : ISODate("2013-02-15T12:22:29.476Z"),
  "activated" : true,
  "deleted" : false,
  "address" : "",
  "city" : "",
  "province" : "",
  "postalCode" : "",
  "country" : "",
  "activationDate" : ISODate("2013-02-15T12:22:29.476Z")
}

Para ello se puede utilizar la siguiente query usando la clausila $where con una instrucción en javascript.

 {$where:"this.email == this.username"}

El resultado de la ejecución será más lento de lo habitual porque en motor de javascript entra en funcionamiento.

No es recomendable para coleccione con muchos documentos.

Referencia:
Mongodb query with fields in the same documents

viernes, 17 de mayo de 2013

SpringData MondoDb: Configuración de conexiones PRODUCCION

Establecemos los valores de la conexión de SpringData para MongoDb en producción basándonos en el siguiente artículo encontrado en StackOverflow: How to configure MongoDB Java driver MongoOptions for production use?

auto-connect-retry="true" : para que el servidor se reconecte se pierde la conexión.

connections-per-host="40"  :  Conexiones que tendrá nuestra aplicación, son la que va a establecer del driver de java para esta aplicación.

connectTimeout = "30000": El el tiempo que espera el servidor antes de abortar un intento de conexión con la base de datos. O sea es el tiempo que espera para conseguir una conexión libre. Debe de ser algo grande entre 15 y 30 segundos para que sea realista según recomiendan.

socketTimeout="60000" : Una vez iniciada un operación de lectura, es tiempo que el socket va  a esperar la respuesta, si se supera podremos tener errores del tipo:

--
Caused by: com.mongodb.MongoException$Network: can't say something
 at com.mongodb.DBTCPConnector.say(DBTCPConnector.java:194)
 at com.mongodb.DBTCPConnector.say(DBTCPConnector.java:155)
 at com.mongodb.DBApiLayer$MyCollection.update(DBApiLayer.java:349)
 at com.mongodb.DBCollection.update(DBCollection.java:177)
 at com.mongodb.DBCollection.save(DBCollection.java:817)
 at com.mongodb.DBCollection.save(DBCollection.java:785)
 at org.springframework.data.mongodb.core.MongoTemplate$10.doInCollection(MongoTemplate.java:885)
 at org.springframework.data.mongodb.core.MongoTemplate.execute(MongoTemplate.java:388)

Caused by: java.net.SocketTimeoutException: Read timed out
 at java.net.SocketInputStream.socketRead0(Native Method)
 at java.net.SocketInputStream.read(SocketInputStream.java:150)
 at java.net.SocketInputStream.read(SocketInputStream.java:121)
 at java.io.BufferedInputStream.fill(BufferedInputStream.java:235)
 at java.io.BufferedInputStream.read1(BufferedInputStream.java:275)
 at java.io.BufferedInputStream.read(BufferedInputStream.java:334)
 at org.bson.io.Bits.readFully(Bits.java:46)
--

Referencia útil: connectionTimeout VS SocketTimeout

maxWaitTime = "1500" : Milisegundos que un hilo esperará  para conseguir una conexión libre del pool de conexiones.

Aquí os dejo la configuración que por ahora nos funciona correctamente.
--
<mongo:mongo host="xxx.xxx.xxx" port="xx" id="mongo">
   <mongo:options connections-per-host="40"
            threads-allowed-to-block-for-connection-multiplier="1500"
            connect-timeout="30000"
            max-wait-time="1500"
            auto-connect-retry="true"
            socket-keep-alive="true"
            socket-timeout="60000"
            slave-ok="true"
            write-number="1"
            write-timeout="0"
            write-fsync="true"/>
</mongo:mongo>

--

jueves, 9 de mayo de 2013

Instalación de MongoDb en Windows 7


En este rápido post vamos a ver como se instala de una manera muy fácil MongoDB en nuestro sistemas Windows.

1 - Para hacerlo lo que necesitamos es descargar MongoDB a nuestra ordenador e instalarlo (o descompromirlo) según la versión que utilicemos aquí podemos encontrarlo el paquete de descarga.

Dependiendo del sistema operativo que utilicemos descargaremos una u otra en mi caso con Windows 7



2 - Descomprimimos el zip en la ruta que queramos, en mi caso lo he puesto c: de tal modo que el directorio de instalación es C:\mongodb-win32-2.4.1

3 - Debemos de crear un directorio para guardar los archivos de base de datos, la documentación nos da un directorio de instalación por defecto que es c:\data\db. Podemos crearlo o establecer uno distinto en los parámetros de arranque de mongo con la opción --dbpath

Yo prefiero definir el directorio dentro de la propia carpeta de instalación por lo tanto  creo la siguiente ruta de directorios

C:\mongodb-win32-2.4.1\data\db

4  - Creación del script de arranque:  Para no tener que estar poniendo el comando de arranque todo el tiempo creo un archivo start_mongo.bat dentro del directorio bin, con el siguiente código:


mongod.exe --dbpath ..\data\db

5 - Arrancamos mongo: Ejecutamos el script de arranque pulsando sobre nuestro archivo .bat o desde una ventana de commando de windows y desde el directorio bin escribimos el código del punto 4.


Ya tenemos arrancada nuestra base de datos.

6 - Ahora arrancamos la Shell de MongoDB para poder operar con la base de datos.

Desde una nueva ventana de comandos accdemos al direcorio bin y ejecutamos:

mongo.exe




Ya podemos operar con nuestra base de datos en LOCAL.

Para operar podemos ver las base de datos que tenemos disponibles:

show dbs

y seleccionamos la base de datos que deseemos con el comando user.

use test

Una vez seleccionada la base de datos ya podemos insertar registros

db.test.save({a:1})

y recuperarlos:

db.test.find()




Ya tenemos la base de datos lista para operar.











viernes, 26 de abril de 2013

Encuesta sobre empleo en el sector informático

Mi web de referencia en cuanto a Java, www.javahispano.org,  nos pide ayuda para llegar a más gente y poder completar la encuesta sobre como está nuestro sector.

Podéis completar la encuesta y a su vez ver los resultados de la que se hizo hace 6 meses una vez completada.

lunes, 22 de abril de 2013

Flex: TextInput prompt no aparece en Popup

El problema con el que he encontrado esta semana es que si tengo un Popup, ya sea utilizando el componente de Flex 4 PopUpAnchor o el propio del Framework Parsley ParleyPopup,  si dentro de él ponemos un textInput el prompt no aparece.




--




<fx:Declarations>

<!-- Place non-visual elements (e.g., services, value objects) here -->

<parsley:Configure/>

 <parsley1:ParsleyPopup open="{model.popupVisible}" modal="true" reuse="false">

  <popups:PopUpBase width="{stage.width}" height="{stage.height}" showEffect="Fade"    hideEffect="Fade" removedEffect="Fade"/>

 </parsley1:ParsleyPopup>

</fx:Declarations>



--

Para solucionarlo tenemos que crear un group que englobe a todo lo que está dentro del pop que implemente la interfaz IFocusManagerContainer, ya que es el Focus Manager lo que está provocando este mal comportamiento.


--
public class PopUpGroup extends Group implements IFocusManagerContainer
  
 {
  
  public function PopUpGroup()
   
  {
   
   super();
   
  }
  
  
  
  public function get defaultButton():IFlexDisplayObject
   
  {
   
   return null;
   
  }
  
  
  
  public function set defaultButton(value:IFlexDisplayObject):void
   
  {
   
  }
  
 }



--


<parsley1:ParsleyPopup open="{model.popupVisible}" modal="true" reuse="false">
 <group:PopUpGroup>       
  <popups:PopUpBase width="{stage.width}" height="{stage.height}" showEffect="Fade" hideEffect="Fade" removedEffect="Fade"/>
 </group:PopUpGroup>
</parsley1:ParsleyPopup>


--



Referencia:

TextInput in a pop up doesn't display its promptDisplay ? Bug or a FocusManager issue ?

miércoles, 17 de abril de 2013

10 webs útiles para trabajar online

Me ha parecido tremendamente útil esta página y os pongo el link con 12 herramientas muy útiles para trabajar.

12 webs tremendamente útiles que quizás desconocías

Gracias a  por esta gran aportación

Yo os pongo aquí las que utilizaré casi seguro.

Similar Sites: Básicamente sirve para encontrar webs similares en cuanto a temática a una que introduzcamos. 

Online OCR: Si alguna vez te diste cabezazos contra la mesa por tener que transcribir un texto ya impreso, no te los volverás a dar gracias a esta web.

Bounce: Cuando necesitemos hacer una captura completa de una página web, Bounce es nuestro servicio.

I Want My Name: Cuando necesitemos comprobar si un dominio está libre, 

Screenr: Para grabar nuestra actividad en pantalla, tanto para Mac como para PC, sin necesidad de descargar ningún software, funciona online. Su limitación es que no permite grabar vídeos de más de 5 minutos.

Font Squirrel: Para los amantes de las tipografías.

Office Templates: Una sección de la web oficial de Microsoft Office para descargar plantillas para Excel, Word, PowerPoint... Básicamente, una forma de conseguir documentos más visuales y hermosos sin apenas esfuerzo.

Copy Paste Characteruna web creada específicamente para ello es quizás la mejor opción. 

Join: Permite compartir lo mostrado en nuestra pantalla con otros usuarios, como hace por ejemplo Google+ en sus hangouts. Una de las webs útiles para quienes necesitan hacer tutoriales en directo,  ni siquiera pide un registro previo, sino que funciona a través de emparejamientos mediante la inserción del mismo código.

Stock.xchng: Tras este peculiar nombre está quizás el mejor servicio para descargar imágenes de stock de forma gratuita.


miércoles, 10 de abril de 2013

Hoy un poco de motivación: “Lo importante no es llegar sino ir"

He leído este artículo de Jose María Dempere: Si no planificas, planificas tu fracaso y me quedo con los conceptos importantes que reproduzco a continuación.

“Lo importante no es llegar sino ir.” Robert Louis Stevenson

La clave para ser eficientes y resolutivos es trabajar desde el presente para crear el futuro. Con pequeñas acciones en el día a día estamos caminando hacia un objetivo. Pero…¿sabemos cual es este objetivo? Si lo sabemos, caminaremos. En caso contrario pasearemos haciendo círculos,

Para caminar, hemos de parar y planificar. Hemos de hacernos la pregunta: ¿Dónde quiero estar dentro de cinco años? ¿A qué me quiero dedicar? 

Tenemos una brújula interior que nos dirige. Sabremos que estamos en el buen camino si sentimos que nos encontramos bien, lejos de preocupaciones y temores, y notamos que avanzamos. Al actuar, llegaran las posibilidades y cada meta superada hará aumentar nuestra confianza y autoestima. Seguro que aparecen obstáculos, pero hemos de desarrollar nuevos recursos para superarlos. Seguro que nos equivocaremos. Perfecto. Esto significa que nos movemos.

Ahora nosotros tenemos el timón.

"La vida es muy peligrosa. No por las personas que hacen el mal, sino por las que se sientan a ver lo que pasa." Albert Einstein.

A por ello!!!!!!.

Keep Pushing!!! Never Give up.


lunes, 25 de marzo de 2013

java -classpath alternativa a java -jar

Este post que o pongo hoy es debido a la guerra que me está dando la generación de un archivo JAR ejecutable de tal modo que todas las librerías de las que depende para funcionar estén dentro del JAR.

El programa es un método public static void main() de toda la vida que queremos que se arranque por línea de comandos para realizar una serie de operaciones como un daemon ejecutándose cada cierta periodicidad.

El programa lazado en eclipse se lanza perfectamente y funciona, pero una vez empaquetado con eclipse para ejecutarse como Jar no funciona.

La manera en la que he intentado ejecutarlo es la siguiente:


java -jar DaemonBatch-1.1.0.jar

JAR

y dentro del Jar tenemos su correspondiente archivo de Manifest.MF con todo lo necesario para la ejecución, la clase a ejecutar  las dependencias y el classpath.


Manifest-Version: 1.0
Rsrc-Class-Path:  aspectj-1.6.12.jar
 spring-security-3.1.0.RELEASE-ldap.jar spring-security-3.1.0.RELEASE-
 config.jar httpcore-4.1.jar aopalliance-1.0.jar spring-security-3.1.0
 .RELEASE-core.jar org.springframework-3.1.1.RELEASE-transaction.jar j
 stl-1.2-api.jar blazeds-4.0.0.14931-rds-server.jar javamail-1.4.5.jar
  org.springframework-3.1.1.RELEASE-instrument.jar spring-security-3.1
 .0.RELEASE-acl.jar spring-security-3.1.0.RELEASE-web.jar .............
Class-Path: .
Rsrc-Main-Class: com.antuansoft.batch.main.Main
Main-Class: org.eclipse.jdt.internal.jarinjarloader.JarRsrcLoader


Lo he exportado de diferentes formas pero siempre me ha dado el mismo error


java.io.FileNotFoundException: URL [rsrc:com/antuansoft/batch/task/] cannot be resolv
ed to absolute file path because it does not reside in the file system: rsrc:com
/antuansoft/batch/task/


Así que he optado por descomprimir el JAR, poner todas las librerias .jar en un directorio lib y ejecutar el siguiente comando para que funcione sin problemas.


java -classpath .;lib/* com.gniux.batch.main.Main

Y ha arrancado sin ningún problema.

Así que si en tu programa no es necesario que este se empaquete todo en un JAR, una alternativa es la que os acabo de proponer.

De todas formas seguiremos investigando.










lunes, 18 de marzo de 2013

Hilos en AS3: Simulación de hilos en action script 3

Para la realización de procesado de datos en cliente que es muy pesado, lo mejor es utilizar hilos, pero Action Script 3 no tiene es capacidad.

Para ello existe una librería que se encarga de simularlos, así que aquí os la dejo para futuros usos, por ahora no he podido hacer ningún ejemplo.

ENDER_LIBhttp://code.google.com/p/ender-lib/

jueves, 14 de marzo de 2013

Recuperar Datos de Disco duro Externo con EASEUS Data Recovery

Creo a que todos nos ha pasado alguna vez que hemos copiado algo en un disco duro externo, de estos que se conectan mediante USB, y vimos como se estaban copiando los datos pero al llegar a nuestro ordenador vemos que no se ha copiado nada.

Es lo típico que suele pasar cuando quitamos el conector USB del ordenador sin seleccionar la opción "Quitar Hardware con seguridad".

Con esta herramienta que os presento he recuperado los datos perdidos en el disco duro, ha sido gratificante porque eran los datos que una amiga había salvado antes de formatear el PC y ya creía que los había perdido.

La herramienta es :

EASEUS Data Recover


Es una herramienta bastante intuitiva, para recuperar la información yo seleccioné la opción  de complete recovery y la herramienta estuvo analizando del disco duro(de 500GB) durante 5 horas para después mostrarme la lista de los archivos que nos da la posibilidad de recuperar.



Importante: No debemos de usar el disco duro para nada desde la pérdida de los datos, ya que podemos perder los datos que están ahí. Sobre todo no debemos de grabar datos ya que los sectores del disco duro podrían sobre escribirse con los  nuevos archivos y entonces la información si que estaría perdida.

La limitación es que sólo te permite recuperara hasta 1GB de datos perdidos, así que si no es mucho la solución ya la tenéis pero para más cantidad de información es necesario poner le Serial Key, que tenemos en este vídeo de You tube.

Serial key

Y en este enlace está todo junto por si acaso desaparecen alguno de los enlaces.

EASEUS Date Recovery + key



lunes, 11 de marzo de 2013

mxmlc Use Flash Text Engine in MX components

En ciertos casos es posible que tengamos ciertos componentes en Flex que no son Sparks y sea necesario skinearlos.

Por ejemplo los tooltips no son skineables, pero se les puede dar estilo gracias al uso de CSS al ser un componente MX.

tooltip

Para que ese estilo de tu CSS funcione con los componentes MX hay que habilitar la siguiente opción del Flex Compiler: Use Flash Text Engine in MX components



El problema es que para hacer la compilación a través del compilador MXMLC esa opción aunque aparece en las opciones de compilación de flex 4  (opción defaults-css-files) parece que al compilar no funciona.

La alternativa para conseguir el mismo efecto en nuestra aplicación es utilizar coger la hoja de estilo que tiene por defecto el flash builder (MXFTEText.css) situada en

[FLEX_4.6_SDK_PATH]\frameworks\projects\spark

Se importa en el mxml principal de nuestro proyecto en combinación con nuestra CSS ya creada y el efecto es el mismo que habilitar la opción.

MainApp.mxml

<fx:Style source="assets/css/MXFTEText.css"/>

<fx:Style source="assets/css/common.css"/>



Common.css
@namespace s "library://ns.adobe.com/flex/spark";

@namespace mx "library://ns.adobe.com/flex/mx";



mx|ToolTip

{

 backgroundColor: #3085B7;

 color: white;

 fontAntiAliasType: advanced;

 fontFamily: "DINPRegular";

 fontSize: 12;

 cornerRadius: 0; 

}


Referencia:

How to use the -fteInMXComponents compiler option with flexmojos











viernes, 8 de marzo de 2013

mxmlc error: Unable to resolve resource package

En español:  [mxmlc] Error: No se puede resolver el paquete de recursos "X".

Este error se produce cuando estamos realizando la compilación de un proyecto a través del comando mxmlc ya se por línea de comandos o a través de ANT, y el compilador no puede compilar uno de nuestros archivos de properties de i18n (intenacionalización).

Para solucionarlo tenemos que añadir la siguiente línea tantas veces sea necesario como idiomas estemos utilizando.


<mxmlc ....
.....
<compiler.source-path path-element='${APP_ROOT}/locale/es_ES'/>

<mxmlc/>

donde ${APP_ROOT} es la ruta donde está nuestro proyecto.


miércoles, 6 de marzo de 2013

Compilación Flex mxmlc con RSL: El orden de compilación de las RSL importa mucho

Cuando compilas tu aplicación Flex y lo haces con RSL externas para que el SWF generado pese lo menos posible (Opciones de compilación MXMLC static-rsls="false") y el orden de las RSL no es el correcto se produce el siguiente error:







VerifyError: Error #1014: flashx.textLayout.container::TextContainerManager is not found

Este error se produce al acceder con tu navegador a la aplicación, el SWF se descarga pero el error que hemos visto.

Esto se produce porque el orden que estableces en las librerías RSL en la compilación de tu SWF es el orden en que estas se descargarán del servidor.

Por lo tantos si ponemos el orden incorrecto de  las librerías al compilar, al descargar y ejecutarse el swf  de la aplicación se descargarán las librerías .swz en el orden incorrecto y el error de que una librería no se encuentra aparecerá.

El orden correcto lo podemos encontrar en nuestra FLEX SDK (en mi caso 4.6) en el archivo flex-config.xml que está en la ruta:

[FLEX_SDK_4.6_PATH]/frameworks/flex-config.xml

A continuación os pongo el comando de apache ANT que utilizo para compilar para que veáis el orden en que hay que poner las librerías .swz para que luego se descarguen correctamente. Se ve en el apartado de las

<runtime-shared-library....

Variables de ANT:

${APP_ROOT} Es la ruta física de la aplicación.
${DirectorioXmlReport} Directorio donde se crea el XML con la dependencias del proyecto.
${FLEX_HOME} Es la ruta donde está instalado el framework de flex ([FLEX_SDK_4.6_PATH])



--
<mxmlc  file="${APP_ROOT}/MyApp.mxml" keep-generated-actionscript="false" 
     output="${APP_ROOT}/${SwfDestination}/${modulo}.swf"
  actionscript-file-encoding="UTF-8"     
  services="${APP_ROOT}/WEB-INF/flex/services-config.xml"
  context-root="MyApp"    
  link-report="${DirectorioXmlReport}/report.xml"
  static-rsls="false"
        incremental="false" warnings="false" fork="true" maxmemory="512m">
  
 <!-- Compilación para la versión de Flash Player -->
 
 <target-player>11.1.0</target-player>
 
 <!-- Get default compiler options. -->
 <load-config filename="${FLEX_HOME}/frameworks/flex-config.xml"/>

 <!-- List of path elements that form the roots of ActionScript
        class hierarchies. -->
        <source-path path-element="${FLEX_HOME}/frameworks"/>
     
 <!-- List of SWC files or directories that contain SWC files. -->
        <compiler.library-path dir="${APP_ROOT}" append="true">
            <include name="libs" />
      </compiler.library-path>  

<!-- Parámetro para modificar el color de fondo al cargar el preloader de la aplicación-->
 <default-background-color>0x252e39</default-background-color>
 
<!-- Parametro adicional al flex compiler para incluir los .properties-->            
 <include-resource-bundles>resources</include-resource-bundles> 

<!-- Asociación de los RSLs para optimización para separar el Framework de flex de nuestros módulos.-->
     
      
<runtime-shared-library-path path-element="${FLEX_HOME}/frameworks/libs/framework.swc">
   <url rsl-url="framework_4.6.0.23201.swz"/>
   <url policy-file-url=""/>
   <url rsl-url="framework_4.6.0.23201.swf"/>
   <url policy-file-url=""/>
  </runtime-shared-library-path>

<runtime-shared-library-path path-element="${FLEX_HOME}/frameworks/libs/textLayout.swc">
   <url rsl-url="textLayout_2.0.0.232.swz"/>
   <url policy-file-url=""/>
   <url rsl-url="textLayout_2.0.0.232.swf"/>
   <url policy-file-url=""/>
  </runtime-shared-library-path>   
 
<runtime-shared-library-path path-element="${FLEX_HOME}/frameworks/libs/spark.swc">
   <url rsl-url="spark_4.6.0.23201.swz"/>
   <url policy-file-url=""/>
   <url rsl-url="spark_4.6.0.23201.swf"/>
   <url policy-file-url=""/>
  </runtime-shared-library-path>    
 
<runtime-shared-library-path path-element="${FLEX_HOME}/frameworks/libs/sparkskins.swc">
   <url rsl-url="sparkskins_4.6.0.23201.swz"/>
   <url policy-file-url=""/>
   <url rsl-url="sparkskins_4.6.0.23201.swf"/>
   <url policy-file-url=""/>
  </runtime-shared-library-path>    
 
<runtime-shared-library-path path-element="${FLEX_HOME}/frameworks/libs/rpc.swc">
   <url rsl-url="rpc_4.6.0.23201.swz"/>
   <url policy-file-url=""/>
   <url rsl-url="rpc_4.6.0.23201.swf"/>
   <url policy-file-url=""/>
  </runtime-shared-library-path>    

<runtime-shared-library-path path-element="${FLEX_HOME}/frameworks/libs/charts.swc">
   <url rsl-url="charts_4.6.0.23201.swz"/>
   <url policy-file-url=""/>
   <url rsl-url="charts_4.6.0.23201.swf"/>
   <url policy-file-url=""/>
  </runtime-shared-library-path>   

<runtime-shared-library-path path-element="${FLEX_HOME}/frameworks/libs/spark_dmv.swc">
   <url rsl-url="spark_dmv_4.6.0.23201.swz"/>
   <url policy-file-url=""/>
   <url rsl-url="spark_dmv_4.6.0.23201.swf"/>
   <url policy-file-url=""/>
  </runtime-shared-library-path>    
 
<runtime-shared-library-path path-element="${FLEX_HOME}/frameworks/libs/mx/mx.swc">
   <url rsl-url="mx_4.6.0.23201.swz"/>
   <url policy-file-url=""/>
   <url rsl-url="charts_4.6.0.23201.swf"/>
   <url policy-file-url=""/>
  </runtime-shared-library-path>
  
 
<runtime-shared-library-path path-element="${FLEX_HOME}/frameworks/libs/advancedgrids.swc">
   <url rsl-url="advancedgrids_4.6.0.23201.swz"/>
   <url policy-file-url=""/>
   <url rsl-url="advancedgrids_4.6.0.23201.swf"/>
   <url policy-file-url=""/>
  </runtime-shared-library-path>

 
  
  <!--Metadatos adicionales a incluir en el proyecto-->
   
 
   <!-- Metadatos dependientes de Parsley-->
   <keep-as3-metadata name="Metadata" />
   <keep-as3-metadata name="DefaultProperty" />
   <keep-as3-metadata name="Required" />
   <keep-as3-metadata name="Event" />
   <keep-as3-metadata name="AssignableTo" />
   <keep-as3-metadata name="Inject" />
   <keep-as3-metadata name="InjectConstructor" />
   <keep-as3-metadata name="Publish" />
   <keep-as3-metadata name="Subscribe" />
   <keep-as3-metadata name="PublishSubscribe" />
   <keep-as3-metadata name="Factory" />
   <keep-as3-metadata name="Init" />
   <keep-as3-metadata name="Destroy" />
   <keep-as3-metadata name="Observe" />
   <keep-as3-metadata name="AsyncInit" />
   <keep-as3-metadata name="ManagedEvents" />
   <keep-as3-metadata name="MessageDispatcher" />
   <keep-as3-metadata name="MessageHandler" />
   <keep-as3-metadata name="MessageBinding" />
   <keep-as3-metadata name="MessageInterceptor" />
   <keep-as3-metadata name="MessageError" />
   <keep-as3-metadata name="Command" />
   <keep-as3-metadata name="CommandComplete" />
   <keep-as3-metadata name="CommandResult" />
   <keep-as3-metadata name="CommandError" />
   <keep-as3-metadata name="CommandStatus" />
   <keep-as3-metadata name="ResourceBinding" />
   <keep-as3-metadata name="Selector" />
   <keep-as3-metadata name="Target" />
   <keep-as3-metadata name="Autoremove" />
   <keep-as3-metadata name="Internal" />
   <keep-as3-metadata name="ObjectDefinition" />
   <keep-as3-metadata name="DynamicObject" />

  
  <!--Localización -->
 
   <locale>es_ES</locale>
   <!--Necesario para las RSLs del framework flex-->
   <locale>en_US</locale>


  <!-- Necesario para el source path del Flex Build Paht-->
  <compiler.source-path path-element='${APP_ROOT}'/>
  <compiler.source-path path-element='${APP_ROOT}/locale/es_ES'/>
 
  <!-- Optimización-->
  <use-network>true</use-network>
     <debug>false</debug>
     <optimize>true</optimize>
  
</mxmlc>  


--