Una vez creada tu aplicación móvil con ionic framework, lo más natural es probarla. Intenté hacerlo con un emulador pero no lo puedes ejecutar al mismo tiempo que otras máquinas virtuales. Así que decidí mejor probarlo en mi teléfono.

Para ello, primero es necesario activar el modo de depuración usb en tu teléfono. Si tienes una versión de Android igual o superior a la 4.2, ve a los ajustes del teléfono->acerca de y busca hasta el final el número de compilación (build number), toca 7 veces y se activará la opción progrmador. Regresa a los ajustes y ve a la opción de programador, activa la depuración usb.
Después, en ubuntu, crea un archivo llamado /etc/udev/rules.d/51-android.rules con el siguiente contenido, reemplazando 0bb4 por el id del proveedor de tu dispositivo, lo obtienes conectando tu teléfono y ejecutando lsusb, son los 4 carácteres antes de los dos puntos

SUBSYSTEM==”usb”, ATTR{idVendor}==”0bb4″, MODE=”0666″, GROUP=”plugdev”

guarda el archivo y agrega permisos de lectura con sudo chmod a+r /etc/udev/rules.d/51-android.rules

Desconecta y vuelve a conectar tu teléfono, te pedirá que aceptes una llave RSA para permitir el acceso de tu computadora, selecciona “aceptar siempre” y acepta. Verifica que puedes acceder a tu dispositivo ejecutando adb devices y debe aparecer en el listado.

Para probar tu aplicación en el dispositivo basta con ejecutar

ionic run android --device

Fuentes:

Anuncios

RoR – Run a ruby gem

enero 16, 2014

Si instalaste ruby a través de rbenv y después instalas un paquete(gem) que proporciona comandos, es necesario ejecutar el siguiente comando para que esten disponibles

rbenv rehash

de lo contrario te mostrará un error parecido al siguiente

$gem install foundation
Successfully installed foundation-1.0.4
1 gem installed
Installing ri documentation for foundation-1.0.4...
Installing RDoc documentation for foundation-1.0.4...

$foundation
bash: foundation: command not found

Fuentes:
https://github.com/sstephenson/rbenv/blob/605e691bff4863e5014ba5ad750ad65e3278aea3/README.md#rbenv-rehash

Al desarrollar una aplicación web necesitamos ir viendo como funciona desde nuestro navegador. La forma más sencilla que he encontrado hasta ahora es abrir una terminal, ir a la carpeta del proyecto y ejecutar el siguiente comando

python -m SimpleHTTPServer

Si necesitas algo más avanzado que eso, por ejemplo, Apache con PHP. También puedes ejecutarlo desde la línea de comandos. Lo primero que tienes que hacer es instalarlo.

sudo apt-get install apache2
sudo apt-get install php5
sudo apt-get install libapache2-mod-php5
sudo service apache2 restart

Una vez instalado, crea el archivo ~/bin/pache con el siguiente contenido

    #!/bin/bash
    /usr/sbin/apache2 -DFOREGROUND -d . -f .htaccess -C"PidFile `mktemp`" -C"Listen 8000" -C"Include /etc/apache2/mods-enabled/*.load" -C"Include /etc/apache2/mods-enabled/*.conf" -C"ErrorLog /dev/stdout" -C"DocumentRoot ." -e debug

Hazlo ejecutable

chmod a+x ~/bin/pache

Ve a la carpeta de tu proyecto y ejecuta el comando

cd ~/Projects/demo
pache

En mi caso utilicé initializr para no comenzar el proyecto desde cero. Si te aparece el siguiente mensaje de error o alguno otro parecido

Syntax error on line 86 of ./.htaccess: Invalid command ‘CommandName’, perhaps misspelled or defined by a module not included in the server configuration

tienes que activar algún módulo. En el script que creamos intentamos cargar todos los módulos que estén configurados en tu instalación local (/etc/apache2/mods-enabled). También podrías especificarlos en el archivo .htaccess y la directiva LoadModule Fuentes: http://www.howtogeek.com/howto/ubuntu/installing-php5-and-apache-on-ubuntu/ http://stackoverflow.com/questions/13695391/start-an-apache-server-in-any-directory-from-command-line http://systembash.com/content/apache-2-4-upgrade-and-the-invalid-command-order-error/ http://www.senin.org/2006/11/07/invalid-command-order-perhaps-misspelled-or-defined-by-a-module-not-included-in-the-server-configuration/ http://stackoverflow.com/questions/933959/apache-is-incorrectly-converting-jsp-pages-to-text-plain

Para la implementación de un sistema de mensajes utilicé los llamados overlay types de GWT. Declaré una clase de la siguiente manera

    public class SystemMessage extends JavaScriptObject {</p><pre><code>    protected SystemMessage() {
    }

    public final native String getId()/*-{
        return this.id;
    }-*/;

    public final native String getHtml()/*-{
        return this.html;
    }-*/;
}
</code></pre><p>

Agregué a esta clase un método para obtener los mensajes del sistema desde un servicio REST

    public static void getMessages(final AsyncCallback<SystemMessage[]> callback) {
        try {
            RequestBuilder rb = new RequestBuilder(RequestBuilder.GET,
                    URLRESTSYSTEMMESSAGES);
            rb.sendRequest(null, new RequestCallback() {</p><pre><code>            @Override
            public void onResponseReceived(Request request,
                    Response response) {
                if (response.getStatusCode() == 200) {
                    JavaScriptObject jsResponse = JSON.decode(response
                            .getText());
                    DSResponse dsResponse = new DSResponse(JSOHelper
                            .getAttributeAsJavaScriptObject(jsResponse,
                                    "response"));
                    if (dsResponse.getStatus() == 0) {
                        JavaScriptObject[] array = JSOHelper
                            .getAttributeAsJavaScriptObjectArray(dsResponse.getJsObj(),
                                        "data");
                        SystemMessage[] messages = (SystemMessage[]) array;
                        callback.onSuccess(messages);
                    }
                } else {
                    callback.onFailure(new Exception(response.getText()));
                }
            }

            @Override
            public void onError(Request request, Throwable exception) {
                callback.onFailure(exception);
            }
        });
    } catch (Exception e) {
        callback.onFailure(e);
    }
}
</code></pre><p>

El servidor nos regresa una respuesta en JSON parecida a la siguiente

    {"response":{ "status": 0, "data": [{"id":"1", "html": "Mensaje 1 
"},{"id":"2", "html": "Mensaje 2 
"}]}}

El problema es que este código no marca errores, incluso funciona correctamente cuando lo ejecuto en DevMode. Pero cuando hice el deploy en un servidor JBoss e intenté ejecutarlo, simplemente no me mostraba los mensajes pero tampoco registraba algún error en la consola. Después de muchísimas líneas de log.info() llegué a la conclusión que el problema era el casting del array. Intenté hacer un ‘cast’ de un array de tipo JavascriptObject[] a uno de tipo SystemMessage[]

    SystemMessage[] messages = (SystemMessage[]) array;

Para hacer el casting de un array en Java tenemos que hacer el casting elemento por elemento.

    SystemMessage[] messages = new SystemMessage[array.length];
    for(int i=0; i<array.length; i++){
        messages[i] = (SystemMessage) array[i];
    }

Nota: intenté utilizar el método Arrays.copyOf() pero éste no ha sido implementado en GWT. Si intentas utilizarlo te arrojará una error parecido al siguiente

The method copyOf(JavaScriptObject[], int, Class) is undefined for the type Arrays

Al hacer un debug de un servicio web, me aparecía la siguiente excepción

Error initializing server: At least one valid code-source or import-shared-library element is required for shared-library “global.libraries” embedded-oc4j/config/server.xml

Al parecer, el problema se debe a que moví el directorio donde instalé JDeveloper, y este guarda la ubicación en el archivo de configuración ~/jdevhome/system/oracle.j2ee.10.1.3.41.57/embedded-oc4j/config/server.xml

Así que tuve que sustituir todas las rutas a la nueva ubicación.

Por ejemplo, cambié

<code-source path="/opt/jdeveloper10133/j2ee/home/applib"/>

por

<code-source path="/home/cirovladimir/Apps/jdeveloper/jdeveloper10133/j2ee/home/applib"/>

Fuentes:
https://forums.oracle.com/forums/thread.jspa?threadID=592789

Cuando tienes varios reportes, es buena idea crear una librería para reutilizar elementos en los reportes. Un ejemplo común es cuando necesitamos usar el mismo encabezado y pie de página para los reportes.

BIRT nos permite agregar algunos elementos dinámicos -tales como el número de páginas, la fecha e incluso un valor obtenido mediante código javascript en un DynamicText- El problema es que esto dependerá de cada reporte, así que ¿cómo agregamos elementos dinámicos desde una librería a nuestro reporte?

Pues habrá que crear una “master page” en la librería donde pongamos elementos “DynamicText” en el encabezado y que estos desplieguen el valor de un parámetro. Después podemos modificar el valor del parámetro en cada reporte, y así, tener un título personalizado pero manteniendo el formato.

Si además, queremos obtener el título mediante una consulta a la base de datos. Lo que tenemos que hacer es crear el DataSource a la base de datos y un DataSet con la consulta que obtiene el título, por ejemplo


SELECT DESCRIPCION
FROM OFICINAS
WHERE ID=:OFICINA

Luego, debemos poner el siguiente código en el evento “beforeFactory” de nuestro reporte


//public final static int MODE_GENERATION = 1; //This mode is for generate the report document. Typically used in Report Engine run task
//public final static int MODE_PRESENTATION = 2; //This mode is for present data that saved in report document, without further data manipulation operation. Typically used in report engine render task
//public final static int DIRECT_PRESENTATION = 3;//This mode is to execute the data query without create report document. It is used in report engine runAndRender task.
//public final static int MODE_UPDATE = 4; //This mode is used to update the existing report document with new queries. Typicially used in IV.
importPackage( Packages.org.eclipse.birt.report.model.api );
importPackage(Packages.java.lang);
importPackage(Packages.java.util);
importPackage(Packages.org.eclipse.birt.report.data.adapter.api);
importPackage(Packages.org.eclipse.birt.report.model.api);
importPackage(Packages.org.eclipse.birt.data.engine.api.querydefn);
var myconfig = reportContext.getReportRunnable().getReportEngine().getConfig();
var des = DataRequestSession.newSession(myconfig, new DataSessionContext(3));
var dsrc = reportContext.getDesignHandle().findDataSource("dsrcOficina");
var dset = reportContext.getDesignHandle().findDataSet("dsetOficina");
des.defineDataSource(des.getModelAdaptor().adaptDataSource(dsrc));
des.defineDataSet(des.getModelAdaptor().adaptDataSet(dset));
var paramBinding = new InputParameterBinding("param_1", new ScriptExpression("\""+ params['IDOFICINA'].value +"\"") );
queryDefinition = new QueryDefinition( );
queryDefinition.setDataSetName( "dsetOficina" );
queryDefinition.addInputParamBinding( paramBinding );
queryDefinition.setAutoBinding(true);
var pq = des.prepare( queryDefinition );
var qr = pq.execute( null );
var ri = qr.getResultIterator( );
if ( ri.next( ) )
{
params["Titulo"].value = ri.getString("DESCRIPCION");
}
ri.close( );
qr.close( );
des.shutdown( );

Es importante poner los nombres exactamente igual que en el diseñador.
En nuestro caso, el parámetro “IDOFICINA” es de tipo String, así que lo ingresamos de la siguiente manera


var paramBinding = new InputParameterBinding( "param_1",new ScriptExpression("\""+ params['IDOFICINA'].value +"\"") );

si fuera un Integer tendría que ser de la siguiente manera


var paramBinding = new InputParameterBinding( "param_1",new ScriptExpression(params['IDOFICINA'].value) );

El valor de ScriptExpression debe ser un bloque de javascript válido, cómo si lo ingresaramos en la ventana “ExpressionBuilder” 🙂

Fuentes:
eclipse forums
birt exchange

XAMPP es una forma fácil de instalar la distribución Apache que contiene MySQL, PHP y Perl. XAMPP es realmente simple de instalar y usar – basta descargarlo, extraerlo y comienzar.

Al menos, eso es lo que dice en su sitio web http://www.apachefriends.org/es/xampp.html. Pero para mi fue otra historia. Primero porque lo quise instalar y ejecutar con mi usuario “normal”. Al querer iniciar los servicios con el comando “lampp start” me arrojó inmediatamente el mensaje de que necesitaba ejecutarlo como “superusuario (root)”. Después de buscar un rato en Google sin éxito, y teniendo en cuenta que los servicios y puertos que se utilizan requieren cierto privilegios, lo ejecuté como root. Fue entonces cuando deje de creer que era simple y fácil de utilizar, debido a que ahora me mostraba el siguiente error:

XAMPP is currently only availably as 32 bit application. Please use a 32 bit compatibility library for your system

En Google te sugieren que instales las librerías ia32-libs si quieres ejecutar XAMPP en un sistema operativo a 64 bits. Yo, ya las tenía instaladas.

Finalmente encontré que debes (no es opcional) instalar/ejecutar XAMPP en el directorio /opt. Una vez que lo extrajé en /opt lo pude ejecutar sin problemas.