viernes, 6 de junio de 2014

[Hibernate] MappingException: property mapping has wrong number of columns

Ésta es una entrada rápida para evitar perder dos días de trabajo como me ha ocurrido. Sé que hacía mucho que no escribía, pero esta nota debe ser recordada, ya que lo que no se apunta, se olvida.

En un proyecto que hace uso de Hibernate para persistir datos en una base de datos PostgreSQL desde clases Java, estaba obteniendo la excepción "MappingException: property mapping has wrong number of columns" a la hora de crear los bean de los objetos mapeados.

Buscando en internet, aparecen decenas de entradas en blogs y foros diciendo que ese error aparece en casos en los que el mapeo es erróneo, y bien en la clase que se muestra en la excepción se han declarado atributos del tipo java.lang.Object o bien están definidos en el XML del mapeo como Object (ambas cosas no son soportadas por Hibernate, por lo visto).

Al estar haciendo el mapeo a través de anotaciones, la segunda opción estaba descartada y, tras revisar numerosas veces la clase en cuestión, la primera no tenía sentido...

Lo que no vi mencionar en ningún sitio es que debía poner estas anotaciones en la declaración de los atributos y no en el método getter, que normalmente es como lo había hecho. No sé si se trata de algo puntual debido a la configuración de mi proyecto o no, pero la cuestión es que se solucionó al cambiar esto:

        private String mmpIdParametro;

@Id
@Column(name = "COLUMNA", unique = true, nullable = false, length = 64)
public String getColumna() {
return this.mmpIdParametro;
}

Por esto:

        @Id
@Column(name = "COLUMNA", unique = true, nullable = false, length = 64)
        private String mmpIdParametro;

public String getColumna() {
return this.mmpIdParametro;
}

No sé si esto servirá a alguien más, pero si le puedo ahorrar a tan solo una persona el trago de perder 2 días de trabajo por semejante chorrada, me doy por satisfecho.

domingo, 24 de marzo de 2013

Google - Trucos para aparecer en las búsquedas de Google

Hace ya algún tiempo que estuve investigando qué podemos hacer para que nuestros sitios web puedan aparecer en las primera páginas de las búsquedas de google relacionadas. Esta investigación me hizo aprender algunos trucos que todos los desarrolladores web pueden poner en práctica su sus portales.

Lo primero que hay que decir es que este proceso no es algo matemático. Influye mucho el número de visitas que tenga tu portal web y la temática del mismo, pero al menos se estará haciendo todo lo que está en nuestras manos para conseguirlo.

  • Elige bien tus palabras clave: Cuando vayas a definir las palabras clave de tu sitio web (recordemos que se definen en la cabecera del código HTML de cada página) debes sólo incluir aquellas que representen bien el contenido del sitio. Debes seleccionar 2 o 3, a lo sumo, que se mantengan constantes en todas las secciones de tu web y el resto deberían ser específicas de la sección en la que se encuentran, de este modo, Google será capaz de filtrar mejor los contenidos. No abuses de palabras claves, cuantas menos sean y más relacionadas estén con tu página web, mejor.
  • Asegúrate de que tu sitio web está bien diseñado: Enlaces rotos y demasiado contenido extraído directamente de otras páginas web, por ejemplo, pueden hacer que Google no te incluya en todas las búsquedas en las que podría aparecer tu sitio web.
  • Haz un sitemap y dáselo a conocer a Google: Cuando tu portal esté terminado y subido a la red, puedes usar Google XML Sitemaps plugin para crear un fichero XML con el mapa de tu página web. Una vez lo tengas, puedes usar las Herramientas para webmaster de Google para dárselo a conocer, añadiendo previamente la URL a tu lista de sitios.
  • Configura bien el sitio que has creado en las herramientas de Google: Hay muchos parámetros configurables en las herramientas mencionadas en el punto anterior que nos ofrece Google, como el área geográfica de destino principal o la frecuencia de rastreo de Goole. Asegúrate de que satisfacen tus necesidades.
  • Si tienes contenido propio, haz uso de otra herramienta de Google: Google ofrece esta herramienta para dar a conocer el contenido propio, como libros electrónicos, portales de empresas o tiendas, comunidades...
  • Haz uso de Google Analytics: Esta herramienta, además de permitirte conocer estadísticas de visitas a tu página web, hará que Google tenga una referencia más a tu portal.
  • Envía tu URL a los índices de Google: Puedes hacer uso de la herramienta que ofrece Google para ello. Tardas sólo unos segundos y te aseguras de que Google visitará tu página para analizarla. Existen herramientas similares para otros buscadores, como Bing o Yahoo.
  • Sácale partido a tus redes sociales: Las redes sociales suelen incluir un apartado en tu perfil para tus URL. Añade este sitio a tu perfil o a un perfil creado específicamente para esta web, de forma que otros usuarios puedan conocerla. Además, publicita tu sitio web en las redes sociales. Cuantas más veces aparezca tu URL en Facebook o Twitter, por ejemplo, además de tener más visitas, más posibilidades tendrá Google de conocer tu portal.
  • Publicita tu sitio web: Al igual que en las redes sociales, Google puede encontrar una URL hacia tu sitio web en cualquier parte de la red, por lo que no es mala idea publicitarla en otras páginas web o foros. El spam masivo no es recomendable, pero si, por ejemplo, en una página de hardware puedes añadir la URL de tu sitio web de software libre, puedes conseguir que las búsquedas de hardware acaben llevando a tu sitio web. Lo que no tiene lógica es que las búsquedas sobre lugares con encanto en España deriven a tu página web, así que mucho ojo con esto.
  • Ofrece contenidos nuevos: Sin duda esta es la mejor forma de conseguir aparecer en las búsquedas de Google. Cuanto más tengas actualizada una página, además de conseguir más visitas, Google más sabrá que ese sitio web sigue activo y seguirá indexándote en las búsquedas.
Además, hay una serie de trucos que podremos utilizar, en combinación con algunos de los anteriores, si lo que queremos promocionar es nuestro blog:
  • Añade tu blog a Google feedburner: Google feedburner es una herramienta que te permite crear feeds de tu blog. Además, dará a conocer a Google las nuevas entradas que vayas escribiendo.
  • Añade tus RSS a páginas de feeds: Hay páginas destinadas a anunciar los seeds de los blogs que se encuentran en la red y podrán hacerte obtener nuevas visitas y hacer que Google registre una mayor actividad en tu blog. Algunas de estas páginas son: Technorati, Alltop y Toprank.
Una vez hechas todas estas cosas, espera unos días y haz una búsqueda en google con el siguiente texto: [site:XXX], donde XXX es la url de tu portal. Si aparecen resultados, significa que tu página web está incluida en las búsquedas de Google. Ahora sólo es cuestión de paciencia.

viernes, 15 de marzo de 2013

jBoss - Tres excepciones, tres soluciones

Es innegable que trabajar con jBoss tiene innumerables ventajas, pero, en ocasiones, puede darnos una gran cantidad de quebraderos de cabeza. 

Por ejemplo, cuando queremos migrar nuestras aplicaciones desde un servidor Tomcat o Weblogic a un servidor jBoss, la tarea puede complicarse tanto que es posible que estemos días tratando de solucionar el mismo problema sin poder avanzar.

Es por eso que esta entrada está dedicada a las tres (de las muchas) excepciones que más lata me dieron en su día cuando, con mi poca experiencia, traté de migrar unas aplicaciones desde Weblogic hasta jBoss. 

Probablemente no sean las mejores soluciones, pero gracias a ellas logré hacer funcionar la mayor parte de mis entregables. Se aceptan vuestros comentarios con alternativas para completar esta información.

NoClassDefFoundError

Esta excepción es un clásico y, normalmente, se soluciona con simplemente añadir la librería donde se encuentra la clase no encontrada al ClassPath de nuestro entregable. La cosa se complica cuando la clase que no encuentra se encuentra en nuestra JDK, como es el caso de javax/annotation/processing/ProcessingEnvironment, que se encuentra en la librería rt.jar de la instalación de Java y debería de estarse incluyendo de forma automática.

¿Qué podemos hacer en ese caso? Si estamos completamente seguros de que nuestra variable de entorno JAVA_HOME está definida apuntando al directorio raíz de nuestra instalación de Java (en mi caso, jRockit), podemos indicarle a jBoss que nos incluya las librerías que nos están dando problemas.

Para ello, deberemos acceder al módulo sun.jdk (que se encuentra definido en JBOSS_HOME/modules/sun/jdk/main) y editar el fichero module.xml, añadiendo la siguiente línea dentro del tag <include-set>:
<path name="javax/annotation/processing"/>
Eso le indica a jBoss que debe cargar el paquete indicado, en el que se encuentra definida la clase ProcessingEnviroment. Para el resto de clases, el proceso es similar, cambiando simplemente el paquete en el que se define la clase no encontrada.

javax.xml.bind.JAXBException

Concretamente vamos a hablar de la siguiente excepción:
javax.xml.bind.JAXBException: property "com.sun.xml.bind.defaultNamespaceRemap" is not supported
Al parecer esta excepción está causada por un conflicto con las versiones de Jaxb de CXF y la JDK6. Es por eso que la solución más sencilla es añadir un directorio llamado endorsed en el directorio lib de nuestro JAVA_HOME. En él se incluirá las librerías jaxb-api y jaxb-impl, asegurándonos de que tienen la misma versión que se utilizan en CXF.

Reiniciando nuestro servidor jBoss no debería de volver a aparecer este error.

ClassNotFoundException


Este caso, normalmente, es muy similar a la primera excepción que mencionamos, pero, al igual que en ella, se trata de un caso especial. Concretamente, se trata de la excepción:
ClassNotFoundException: com.sun.org.apache.xerces.internal.dom.DocumentImpl
Lo curioso de este caso es que se trata de una clase que se incluye en la JDK6 y, aunque la incluyamos de forma similar a la primera excepción que hemos explicado en esta entrada, no la encuentra de ninguna manera.

Al parecer esta excepción salta ya que las librerías de saaj hacen uso de la librería jaxp-ri, y en ella trata de encontrar la clase DocumentImpl, es por eso que la solución es descargar la versión más actualizada de ésta e incluirla en el mismo módulo en el que se encuentren nuestras liberías de saaj.


Como dije, quizás no sean las mejores solciones, pero son aquellas que a mí me han funcionado. Como siempre, las dudas, comentarios y opiniones, siempre que sean constructivas, son bien recibidas.

miércoles, 13 de marzo de 2013

Liferay - Desplegar portlets en Weblogic en modo producción

La entrada de hoy, además de tener un título largo, ofrece la solución a un problema con el que, en su día, me estuve peleando durante un largo tiempo. Se trata del despliegue de portlets de Liferay en un servidor Weblogic configurado en modo producción. 

Lo primero que habrá que aclarar es qué es eso del modo producción. Se trata de un estado configurable en nuestro servidor que indica que ya no se está realizando desarrollos de los entregables que se instalan en él. Al contrario del modo desarrollo, este estado mantiene activos una serie de mecanismos de seguridad para impedir un mal uso del servidor que pueda poner en peligro los servicios que se están proporcionando.

Existen numerosas diferencias entre el modo desarrollo y el modo producción de un servidor Weblogic (las cuales podéis encontrar aquí), pero la que nos afecta ahora mismo es que en producción no están activos ni el despliegue automático ni el despliegue en caliente de los entregables.

Es por eso que el despliegue de portlets, que normalmente se realiza con despliegue automático (autodeploy), se complica en aquellos servidores Weblogic en modo producción. Y, en este punto, es cuando tenemos que buscar el modo de poder desplegar portlets en nuestro servidor.

Antes de empezar hay que aclarar que esto ha sido probado para Liferay versión 6.1.1, instalado en un servidor Weblogic versión 10.3.6, por lo que no sé si se puede hacer de igual manera con otras versiones. También voy a dar por hecho que ambas herramientas están instaladas correctamente y en funcionamiento.

Los pasos que hay que seguir son los siguientes:

  • Generar un portlet y empaquetarlo utilizando la herramienta Maven. Esto generará el entregable en formato WAR que tendremos que instalar.
  • Se debe editar el fichero portal-ext.properties del entregable de Liferay que tenemos instalado en Weblogic. Este fichero se habrá generado en la instalacción si se han seguido los pasos correctamente, y en él ya se habrán añadido ciertos parámetros de la configuración, como el JNDI del origen de datos asociado al esquema de la Base de Datos al que atacará nuestro portal. En este fichero habrá que incluir la siguiente línea para que liferay trate de hacer un despliegue automático:
auto.deploy.enabled=true
Se pueden añadir otros elementos como los listeners que van a usarse en el despliegue automático o la ruta del directorio dónde se automatizan los despliegues. Hay gran cantidad de información por internet sobre posibles elementos configurables de Liferay.

  • Se reiniciará el servidor para asegurarnos de que los cambios en la configuración se cargan correctamente.
  • Ahora podremos poner nuestro WAR en el directorio que hayamos especificado para los despliegues automáticos. Por defecto, se trata del directorio deploy que se encuentra en el dominio dónde hemos instalado Liferay. Este paso es muy importante, ya que es el que activa el proceso que transforma el WAR en un directorio descomprimido (o exploited) que puede instalarse en nuestro servidor con el contenido del portlet.
  • El directorio generado aparecerá en la ruta que se haya especificado en el fichero portal-ext.properties. Si no se ha indicado nada, el entregable descomprimido que desplegaremos aparecerá en el directorio autodeploy del servidor Weblogic, ya que, por defecto, todo entregable que se ponga en él, se desplegará automáticamente si nos encontramos en modo desarrollo.
  • Al estar en modo producción, este proceso de despliegue automático no se llevará a cabo, por lo que habrá que acceder a la consola de Weblogic e instalar manualmente el entregable descomprimido generado.
Una vez hecho todo esto, el portlet estará listo para ser incluido en nuestro portal.

Espero que os haya sido útil la explicación y ya sabéis: cualquier duda, comentario o sugerencia constructiva será siempre bienvenido.

martes, 12 de marzo de 2013

Liferay - actionURL, renderURL y resourceURL

Quienes han trabajado con Liferay saben de sobra que, al menos al principio, no es un camino de rosas. Ofrece tantas posibilidades que, en ocasiones, esto hace que uno no sepa cuáles elegir si nadie les guía un poco.

Para quien no sepa qué es Liferay, aquí dejo un enlace que explica, en términos generales, qué nos ofrece esta herramienta. Como la mayoría de la buena documentación, está en inglés, pero, ¿qué mejor explicación y guía que aquellas hechas por los propios creadores?

Probablemente acabe escribiendo una gran cantidad de entradas sobre esta herramienta, pero me parece conveniente comenzar con una aclaración de conceptos sobre tres elementos que podremos utilizar en nuestros ficheros JSP y que nos abrirán un sin fin de posibilidades. Hablamos de actionURL, renderURL y resourceURL.

actionURL

Este tag crea una URL que, al asociarse a un enlace HTML (tag <a>), permite la ejecución de un método definido la clase principal de nuestro portlet (aquella que hereda de la clase MVCPortlet) sin que se recargue la página en el navegador. 

Para hacer uso de esta herramienta, se debe añadir en nuestro código JSP el siguiente tag:

<liferay-portlet:actionURL name="metodoPortlet"></liferay-portlet:actionURL>

Esta URL se enlazará con el tag <a> de la siguiente forma: (esto es igual en los tres casos de los que se habla en esta entrada)

<a href="<%=metodoPortlet.toString()%>" /> Haz click aquí </a>

En la clase principal de nuestro portlet tendrá que encontrarse un método público con el mismo portlet que la URL (en este caso, metodoPortlet), el cual será llamado al hacer uso del enlace.

Es posible crear tantos pares de actionURL y métodos como sean necesarios, permitiendo, por ejemplo, la carga y muestra de datos al hacer click en un botón.

renderURL

Este tag ofrece dos posibilidades en función de si en su interior definimos o no un parámetro llamado "jspPage", cuyo valor debe ser la ruta de un fichero JSP.

Si no lo definimos, esta URL nos permitirá, al hacer click en un enlace, se vuelva a ejecutar el método doView() de nuestro portlet, heredado de la clase MVCPortlet, sin necesidad de recargar la página. Para ello, definiremos la URL de la siguiente manera, pudiendo añadir parámetros que se pasarán en método GET:

<liferay-portlet:renderURL var="testRenderURL">
</liferay-portlet:renderURL>
Si definimos el parámetro "jspPage", el funcionamiento será similar, pero cargará el fichero JSP al igual que el método include(). Se definirá, en este caso, del siguiente modo:

<liferay-portlet:renderURL var="testRenderURL">    <liferay-portlet:param name="jspPage" value="/html/portlet/test/test.jsp"/></liferay-portlet:renderURL> 

resourceURL

El funcionamiento de este tag es bastante similar al anterior, con dos excepcione. La primera es que en lugar de ejecutar el método doView(), ejecuta el método serverResource(), que es el recomendado para, por ejemplo, la carga de documentos PDF para visualizarlos en el navegador, entre muchos otros usos.

La segunda diferencia se debe a que no se recomienda cargar ficheros JSP en el método serverResource(), aunque es posible, por lo que no procesa automáticamente el fichero indicado en el parámetro "jspPage" (o, al menos, yo no he encontrado ningún ejemplo en el que ocurra así).

Este tag se define de la siguiente manera:

<portlet:resourceURL var="someUrl" id="veryImportantResource'" ></portlet:resourceURL>

Espero que tras leer esta entrada, al menos se entienda para qué sirve cada una de estas URLs. El resto ya es cuestión de imaginación. Seguro que con un poco de ingenio podréis sacarle un gran partido a estas tres herramientas con miles de posibilidades.

domingo, 10 de marzo de 2013

PHP - Evitar inyección SQL

Uno de los mayores riesgos que pueden aparecer a la hora de crear una página web que haga uso de Bases de Datos SQL es la inyección SQL. Esto se trata, en resumidas cuentas, de la posibilidad de poder forzar a la base de datos a devolver una respuesta que nos convenga para poder hacer un uso inapropiado del portal web.

Un ejemplo sería un formulario de inicio de sesión. En una página web en la que no controlamos este problema ¿qué ocurriría si en el campo usuario ponemos un nombre de usuario correcto y en la contraseña escribimos "' OR '1'='1'"? La respuesta es sencilla: es muy probable que tengamos acceso a la cuenta de ese usuario sin conocer su contraseña.

Ahora que ha quedado claro la gravedad del asunto, voy a poneros unos cuantos puntos a tener en cuenta a la hora de crear formularios que ataquen a nuestra base de datos que harán que, en casi la totalidad de los casos, sea imposible provocar la inyección SQL. 

Hay que mencionar que estos trucos son válidos para páginas web que hagan uso de PHP para atacar a Bases de Datos SQL. De no ser así, es posible que algunos de ellos no puedan ponerse en práctica.

  • Se debe utilizar siempre comillas simple a la hora de delimitar las variables que se vayan a utilizar directamente sobre la consulta a la Base de Datos. Esto hace que los intentos de inyección SQL que no hagan uso de comillas simples no tengan efecto sobre nuestro sistema. Ejemplo:
SELECT usuario FROM tabla_usuarios WHERE usuario= ' $usuario ';
  • Si en alguno de los campos del formulario esperas un tipo de datos concreto (un número, string, etc...), es recomendable hacer uso de la función de PHP gettype() antes de utilizar el dato que nos indica el usuario, ya que devuelve una ristra indicando su tipo.
  • Existe la posibilidad de comprobar si nuestro servidor cambia automáticamente las ristras pasadas por formulario o por URL para evitar la inyección SQL. Esto se puede averiguar ejecutando el siguiente código:
<?if(!isset($_GET["inyeccion"])){ header("location: ?inyeccion='");} else { echo 'Tu servidor '; if($_GET["inyeccion"] != "'")echo 'no '; echo 'tiene problemas de inyección';}?>

  • En caso de que se haya mostrado el mensaje "Tu servidor tiene problemas de inyección", se debería filtrar cada una de las variables obtenidas por formulario o URL haciendo uso del siguiente código, encargado de, por ejemplo, cambiar los caracteres ' por \':
<?// Se filtran las variables pasadas por URL
foreach($_GET as $var=>$valor){   $_GET[$var] = str_replace("'","\'",$_GET[$var]);}// Se filtran las variables pasadas por formularioforeach($_POST as $var=>$valor){   $_POST[$var] = str_replace("'","\'",$_POST[$var]);}?>

  • Se recomienda no hacer uso del operador * en queries SQL, sino indicar explícitamente aquellos campos que se quieren recuperar en la llamada. De este modo, además de evitar que los usuarios del portal puedan acceder a datos que no deberían conocer, hará que la llamada a la Base de Datos sea más óptima y rápida.
  • Hacer uso del usuario root es muy peligroso y debe hacerse con mucha precaución. Si nuestros usuarios de la página sólo van a tener acceso a la visualización de determinadas tablas de nuestra Base de Datos, es recomendable crearles un usuario en nuestro esquema con los permisos correspondientes.
  • Hay que tener mucho cuidado con controlar los mensajes de error que se muestran en el portal. Por defecto, si ocurre algún error al realizar la llamada a la Base de Datos, se muestran mensajes en la parte superior que pueden contener más información de la que los usuarios deberían obtener, además de evidenciar que algo no va bien en nuestro portal. Es por eso que, cuando se vaya a abrir el portal al público, incluyamos siempre una llamada a la función de PHP error_reporting(0), que evita que aparezcan estos mensajes.
  • Por si todo esto no fuera suficiente, existe otra funcion PHP que evitará la inyección SQL. Se trata de mysql_real_scape_string, una función que se está quedando obsoleta (tengo que informarme sobre las nuevas incluidas en las últimas versiones de PHP), a la cual se le pasa una variable y la formatea para evitar problemas por inyección.
Como se ve, evitar la inyección SQL es bastante sencillo si se sigue una serie de pasos que acabarán convirtiéndose en una rutina cuando programemos.

Espero que os sea útil y recordad, toda duda o comentario constructivo es bien recibido y lo contestaré tan pronto como me sea posible.

El comienzo

Los comienzos nunca son fáciles, y más aún cuando se trata de un amante tan exigente como puede llegar a ser un blog, es por eso que este he decidido tomármelo con calma para no repetir errores pasados.

También es cierto que este blog es de un ámbito bastante distinto a los que he escrito en otras ocasiones, ya que se trata de, como bien su nombre indica, un blog de notas. En mi profesión, la informática, gran parte del tiempo del trabajo se pasa investigando y buscando soluciones para problemas que te encuentras día tras día y es por eso que es habitual tener que tomar cientos de notas para no olvidar los pasos a seguir, por si el mismo problema volviera a aparecer.

¿Y qué ocurre cuando llevas cierto tiempo trabajando de esta forma? Pues muy sencillo: tus notas son un caos tal que no encuentras nada de lo que buscas aunque sabes que está ahí. Y es ese el momento en el que, ordenando tus libretas y post-its, piensas: ¿y si comparto estas cosas con aquél al que le pueda interesar? Probablemente no sean muchos los interesados, pero quizás pueda hacer que alguien se ahorre parte de su tiempo navegando en búsqueda de una solución a algún problema.

Así nace Mi Blog de Notas, como un blog en el que escribiré trucos, tutoriales o pasos a seguir para solucionar algunos problemas con los que me he topado.

Debe quedar claro que en ningún momento mostraré ningún contenido que pueda violar la confidencialidad a la que estoy comprometido por mi trabajo, por lo que, si en alguna ocasión muestro algún fragmento de código o algún documento, no se tratará de datos extraídos de los proyectos en los que trabajo o he trabajado, sino de alguna muestra para aclarar conceptos.

Pues sin más, comenzamos. No duden en escribir si hay cuestiones que no queden claras o si conocen alguna alternativa a mis entradas. Siempre que sean comentarios constructivos, serán más que bien recibidos.