Bleg - Interactividad, Usabilidad y Web » Blog Archive » Flex + Apache + Php + mySQL + amfphp + tomcat +fds(lcds) juntos, sin problemas

Flex + Apache + Php + mySQL + amfphp + tomcat +fds(lcds) juntos, sin problemas

15 de Mayo, 2008

En estos momentos ando desarrollando una RIA bastante grande basada en Flex+AMFPHP y conexión con MySQL. Para desplegar el entorno de desarrollo de forma fácil, basta con instalar alguno de los paquetes recopilatorios que incluyen el entorno LAMP (como por ejemplo, XAMPP de los ApacheFriends).

Hasta aquí todo perfecto. El problema surge cuando queremos incorporar a nuestro proyecto (en mayor o menor medida) algunos módulos basados en FDS (Flex Data Services), ahora conocido como LiveCycle Data Services. Esto nos obliga a montar un servidor de aplicaciones J2EE (como Tomcat) junto a nuestro Apache.

La verdad es que para mi proyecto, dadas las dimensiones que ya tiene y a los tiempos de desarrollo tan ajustados, me resulta inviable plantear un refactoring del código para basar el proyecto totalmente en LCDS. Al menos para la primera revisión estable, he decidido mantener AMFPHP e incorporar LCDS para implementar un módulo de Reporting y quizás alguno más para generación de listados de datos y gráficas empresariales a tiempo real (mediante data-push).

Todo esto me hace plantear lo siguiente: ¿a caso no es posible, o incluso deseable, desarrollar un proyecto Flex en el que se incluyan partes con AMFPHP, LCDS e incluso Red5?

En un intento rápido, he tratado de cargar un módulo de generación de PDF existente en Tomcat desde la aplicación principal (basada en Flex+AMFPHP) sin muy buenos resultados.

El problema es que hay muchos problemas y me explico: el app principal corre en Apache (puerto 80) y tomcat en el 8080. Mi aplicación principal es un Flex compilado, mientras que la parte en LCDS es MXML compilado en el servidor. Al llamar de uno a otro, podemos tener problemas de violación de la sandbox y lo que es peor, problemas con los contextos:

En LCDS, configuramos la compilación, linkado, “destinations” y demás mediante ficheros de configuración xml. Concretamente, en el fichero services-config.xml especificamos los endpoints de cada uno de los canales con los que queremos trabajar. Esto es el extracto perteneciente a AMF:

CODE:
<channel-definition id="my-amf" class="mx.messaging.channels.AMFChannel">
<endpoint url="http://{server.name}:{server.port}/{context.root}/messagebroker/amf" class="flex.messaging.endpoints.AMFEndpoint"></endpoint></channel-definition>

<properties>
<polling-enabled>false</polling-enabled> </properties>

Como vemos, en el endpoint del canal, se indican una serie de “variables” que a posteriori se sustituirán por los valores correctos.

He observado que, cuando se llama al módulo desde la aplicación principal (en Apache), dicha información es desconocida y por lo tanto, el módulo no funciona ni para atrás.

Seguramente todo es más fácil de lo que pienso, pero ante todo soy desarrollador, NO administrador; por eso, aunque esos parámetros pueden indicarse tanto en el fichero flex-config.xml como en la propia linea de comandos del compilador, creo muy tedioso e indeseable el estar trasteando con esos parámetros. De hecho y por experiencia, creo que estar “chapuceando” las instalaciones para salir del paso se convierte en un problema insalvable a la larga.

Para mis necesidades, creo que la mejor solución es la siguiente: hacer hablar correctamente a Apache con Tomcat.

Para esto último, lo único que necesitamos es instalar Apache Tomcat Connector. Esto es simplemente un módulo de Apache como otro cualquiera que canaliza, según un fichero de reglas, todas las llamadas necesarias a Tomcat una vez recibidas por Apache y de forma transparente.

Esto nos proporciona enormes posibilidades no sólo para integrar en nuestras aplicaciones módulos de distintas procedencias de manera sencilla; sino que además nos permitirá servir aplicaciones J2EE desde varios servidores a través de Apache (Apache se convierte en una especie de “proxy”), habilitar mecanismos de balanceo de carga, etc….

Al grano….

Instalación de Apache+PHP+MySQL+AMFPHP.

Creo que este apartado no requiere de muchas explicaciones y hay montones de tutoriales por toda la red. En resumen y para los impacientes: descarga XAMPP para Mac Osx, Windows o Linux y descarga e instala AMFPHP como corresponda.

Instalación de Apache Tomcat y LCDS

- Descarga Apache Tomcat desde la web oficial e instala de la manera convencional. Arranca el servicio para comprobar que todo está OK y a continuación paralo nuevamente.

- Descarga el instalador de LiveCycle Data Services desde la web de Adobe.

- Inicia la instalación indicando que quieres una instalación sobre un servidor J2EE existente (no con el JRun integrado). Selecciona como directorio de instalación el directorio principal de aplicaciones de tu Tomcat (por ejemplo, D:\Tomcat_5.5_lcds\webapps). Esto añadirá a dicha carpeta varios ficheros .war que habilitarán LCDS sobre Tomcat.

- Inicia Tomcat y espera un pelín. Tomcat automáticamente se encargará de expandir los ficheros .war de LCDS, creando sobre nuestro directorio webapps correspondiente una nueva carpeta por cada fichero .war existente.

- Una vez compruebes de que todo está arrancado, abre las aplicaciones de ejemplo de LCDS para comprobar que todo está OK: http://localhost:8080/samples.

¡¡Ya casi estamos!!

Instalación y configuración del Apache Tomcat Connector.

Lo primero que deberemos hacer es descargar el módulo correspondiente a nuestra versión de Apache desde esta dirección.

Dentro encontrarás una serie de ficheros, entre los cuales están las librerías .so para nuestro Apache y que tienen la siguiente forma:

CODE:
mod_jk-apache-(version_apache).so

Tan sólo deberemos descargar el fichero correspondiente a la (version_apache) que tenemos instalada.

Ahora guardamos el fichero descargado en el directorio de módulos de apache (en Windows suele ser c:\apache\modules) y renombrar el fichero al nombre mod_jk.so. Este paso es muy importante si queremos evitar problemas a posteriori.

Para mantener las cosas en orden, vamos a crear un fichero de configuración .conf independiente del principal (htttpd.conf).

Creamos un nuevo fichero de texto llamado tomcat.conf con el siguiente contenido:

CODE:
# Carga del módulo apache
LoadModule jk_module modules/mod_jk.so
# Si tenemos instalado una versión de Apache &lt;2.x quizás debamos
# descomentar esta línea para habilitar
# AddModule mod_jk.c
# Ubicación del fichero de configuración del conector (workers.properties)
# Es deseable que ubiques el fichero en el directorio conf para que esté cerca
# del httpd.conf y lo tengamos todo controlado
JkWorkersFile conf/workers.properties
# Dónde poner el fichero de memoria compartida del módulo
JkShmFile logs/mod_jk.shm
# Dónde poner el fichero de log del módulo
# Es deseable que ubiques el fichero en el directorio de logs de
# Apache para tenerlo todo controlado
JkLogFile logs/mod_jk.log
# Especificamos el nivel de log [debug/error/info]
JkLogLevel info
# Especificamos el formato timestamp para el fichero de log
JkLogStampFormat “[%a %b %d %H:%M:%S %Y]
##################################################
# REGLAS DE REDIRECCIÓN A TOMCAT
##################################################
# Aquí añadiremos tantas reglas de redirección como sean necesarias.
# Es importante dejar claro que cada regla de redirección va dirigida a
# un “worker” particular. Podemos tener tantos workers como queramos
# y cada uno de ellos puede ser un Tomcat diferente.
###################################################
#
# Enviamos todo para el contexto /samples al worker llamado “worker1″
JkMount /samples/* worker1

Ahora creamos el fichero workers.properties en la ubicación que hayamos indicado en el fichero anterior y lo rellenamos con el siguiente contenido:

CODE:
#Definimos un worker real usando ajp13 (más sobre esto en la doc oficial)
worker.list=worker1
# Propiedades del worker1 (ajp13)
worker.worker1.type=ajp13
worker.worker1.host=localhost
worker.worker1.port=8009

Por último, tan sólo nos queda incluir nuestro fichero de configuración para su carga con Apache:

Edita el fichero httpd.conf y añade al final del mismo las siguientes líneas:

CODE:
# Configuración del conector Apache-Tomcat
Include conf/tomcat.conf

Pruebas y conclusiones finales.

Para probar que todo está OK, tan sólo debemos abrir http://localhost/samples. Si todo ha ido bien, ¡¡estamos viendo los ejemplos de LCDS sin usar el puerto 8080!!.

Fantástico, a mi me ha facilitado muchísimo el trabajo.

Si tienes algún problema, seguramente Apache ni te cargue correctamente. Intenta arrancar Apache desde consola para así poder ver posibles errores de sintaxis en alguno de los fichero que hemos creado. Lo más probable es que hayas descargado la versión del mod_jk.so errónea para tu versión de Apache.

Ahora podemos demostrar de manera muy rápida la integración y uso directo de Flex en el que cargamos un módulo en Tomcat+LCDS desde una aplicación con Flex+AMFPHP:

Código en aplicación ERP.swf (Apache+AMFPHP):

Actionscript:
<mx:moduleloader id="modPDFReportingModuleLoader">
url="http://localhost/samples/pdfgen/pdfgenModule.swf"
height="100%" width="100%" x="0"/&gt;
<mx:script>
<!--[CDATA[
import modules.ModPDFReporting;
public function createModule():void {
if (!modPDFReportingModuleLoader.url) {
modPDFReportingModuleLoader.url = "http://localhost/samples/pdfgen/pdfgenModule.swf";
return;
}
modPDFReportingModuleLoader.loadModule();
}
public function removeModule():void {
modPDFReportingModuleLoader.unloadModule();
}
]]--></mx:script>

Este es el contenido (simplificado) de pdfgenModule.swf:

Actionscript:
<mx:module xmlns:mx="http://www.adobe.com/2006/mxml">
<mx:script>
<!--[CDATA[
import flash.net.navigateToURL;
import mx.controls.Alert;
import mx.rpc.events.FaultEvent;
import mx.rpc.events.ResultEvent;
import mx.graphics.ImageSnapshot;
private function generatePDF():void
{
service.generatePDF(xmlModel);
}
private function resultHandler(event:ResultEvent):void
{
var url:String = event.result as String;
navigateToURL(new URLRequest(url), "_blank");
}
private function faultHandler(event:FaultEvent):void
{
Alert.show(event.fault.toString(), "Error")
}
]]-->
</mx:script>
<mx:remoteobject id="service" destination="PDFService">
fault="faultHandler(event)"
result="resultHandler(event)" /></mx:remoteobject></mx:module>

Como podemos observar, en este código usamos LCDS para llamar a un destination de tomcat. Lo más importante es que ahora gracias a nuestro conector, el funcionamiento es transparente y se simplifica mucho la realización de módulos independientes e incluso, que varias personas trabajemos en cada parte sin saber muchos detalles acerca de la instalación y configuración puntual que haya sobre Apache, Tomcat, etc.

Si te sirve me cuentas.