Mostrando entradas con la etiqueta JAVA. Mostrar todas las entradas
Mostrando entradas con la etiqueta JAVA. Mostrar todas las entradas

martes, 11 de noviembre de 2014

Apuntes - Tuning Glassfish (Optimización para producción)


Ajuste de JVM


Ya que Glassfish está hecho sobre Java, muchas de las optimizaciones pueden hacerse a través de la Java Virtual Machine


  1. En el fichero domain.xml ubicado en %GLASSFISH_HOME%/glassfish/domains/<DOMAIN_NAME/config se deben editar los parametro Xms y Xmx, esto para reservar más memoria para el GF. Ubica los siguientes parámetros y modificalos según la necesidad y capacidad del server:<jvm-options>-Xmx1024m</jvm-options> y <jvm-options>-Xms1024m</jvm-options>
  2. En este caso se está asignando 1GB de RAM, ambos parámetros se colocan igual para asignar la memoria en el arranque del servicio, de esta forma no se pierde tiempo haciéndolo después.
  3. Modificar la opción -client por -server de la siguiente manera, si el servidor que ejecuta el GF es 64bits entonces por default tomará la opción correcta, pero nada se pierde con “asegurarnos":<jvm-options>-server</jvm-options>
  4.  También incluir estas configuraciones -Xss128k -XX:+DisableExplicitGC-XX:ParallelGCThreads=N (en donde N es el número de CPU's del servidor si la cantidad es menor a 8, en caso contrario N es igual #CPU's/2)

-XX:+UseParallelOldGC 

Si la aplicación está haciendo una gran cantidad de operaciones de E/S como escritura, también se le puede decir a Grizzly que utilice una estrategia asíncrona:
-Dcom.sun.grizzly.http.asyncwrite.enabled=true
Una alternativa que podría considerarse también si se está notando que algunas operaciones de escritura parecen toma más tiempo de lo esperado.  Se puede aumentar el número de procesadores de escritura al aumentar el número Selectors NIO:

-Dcom.sun.grizzly.maxSelectors=XXX 
Si la aplicación será utilizada por dispostivos móviles o a traves de redes lentas puede configurar: 
-Dcom.sun.grizzly.readTimeout 
o 
network-config>network-listeners>network-listener>transport#read-timeout para las operaciones read 
y 
com.sun.grizzly.writeTimeout o network-config>network-listeners>network-listener>transport#write-timeout para las operaciones write. Para que un hilo no bloquee otros posibles procesos de I/O durante mucho tiempo puede configurar la opción:

-Dcom.sun.grizzly.useKeepAliveAlgorithm=true
Esto le dará oportunidad de ejecución a otras peticiones.
GlassFish Tuning

Algunas configuraciones en el servidor de aplicaciones en sí pueden ser las siguientes:

En el mismo fichero domain.xml modificar las siguientes opciones como se muestra a continuación:

1.      <das-config autodeploy-enabled="false" dynamic-reload-enabled="false"></das-config>
2.      Aceptor Threads: Si se tiene por ejemplo un servidor con 2 CPU's de 4 nucleos cada uno, el valor de este parametro debe ser 8. Para configurarlo ve a la consola de administración y busca la siguiente direccion Configuration -> Network Config -> Transports -> tcp -> Acceptor threads
3.      Cacheo de recursos estáticos: Configuration -> Network Config -> Protocols -> http-listener-1 -> File Cache -> Enabled. De tener conexiones HTTPS habilitarlo tambien para el listener seguro.
4.      Si el servidor solo posee un Network Interface Card (NIC) reemplaza todos los valores 0.0.0.0 de  los http listeners con el IP del servidor, como se muestra
Configuration -> Network Config -> Network Listeners -> <listener_name> -> Address
5.      Modificar el fichero default-web.xml ubicado en %GLASSFISH_HOME%/glassfish/domains/<DOMAIN_NAME>/ config como se muestra: 

<servlet>
    <servlet-name>jsp</servlet-name>
    <servlet-class>org.apache.jasper.servlet.JspServlet</servlet-class>
    <init-param>
        <param-name>development</param-name>
        <param-value>false</param-value>
    </init-param>
    <init-param>
        <param-name>genStrAsCharArray</param-name>
        <param-value>true</param-value>
    </init-param>
    ...

</servlet>


Optimizaciones para JDBC

Para drivers JDBC de Oracle pueden configurarse las siguientes opciones:


- ImplicitCachingEnabled=true
- MaxStatements=200
Configurar los valores del Pool de conexiones steady-pool-size y max-pool-size con el mismo valor. Una regla general es configurar estos valores con el mismo número que se ha configurado en los HTTP request processing threads

viernes, 7 de noviembre de 2014

Threads en JAVA, iniciarlos, detenerlos y reanudarlos (Básico)

Bien primero que nada explicar de que vá el asunto.
La idea es controlar la ejecución de un Thread; es decir, poder detenerlo y reanudarlo. De plano que para iniciarlo lo iniciamos en el main y que tambien podemos detener del todo el proceso (para no poder levantarlo más).
Explico un poco el enfoque de la solución, implementé un Proceso principal, este es el trabajo que debe hacer el Thread; simplemente consiste en imprimir un numero cada cierto tiempo random no mayor a 5 segundos.
Decir que esto se ejecutará infinitamente.

Clase Proceso.java

import java.util.Random;

/**
 * @author ropherpanama@gmail.com
 * Esta clase representa el proceso de trabajo; imprimir un entero cada cierto tiempo
 * se sobrescriben los metodos suspend y resume
 */
public class Proceso implements Runnable {
    private int currentCont;
    private Thread t;
    private final int sleepTime;
    boolean suspended = false;
    private String threadName;
    private boolean working = true;
    private final static Random generator = new Random();

    public Proceso(String threadName) {
        this.threadName = threadName;
        sleepTime = generator.nextInt(5000);
        currentCont = 0;
    }

    @Override
    public void run() {
        System.out.println("Running " + threadName);
        try {
            while (isWorking()) {
                System.out.println(threadName + " doing : " + currentCont);
                currentCont++;
                Thread.sleep(sleepTime);

                synchronized (this) {
                    while (suspended) {
                        wait();
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public void start() {
        System.out.println("Starting " + threadName);
        if (t == null) {
            t = new Thread(this, threadName);
            t.start();
        }
    }

    void suspend() {
        System.out.println("Suspending " + threadName);
        suspended = true;
    }

    synchronized void resume() {
        System.out.println("Resuming " + threadName);
        suspended = false;
        notify();
    }

    public boolean isWorking() {
        return working;
    }

    public void setWorking(boolean working) {
        this.working = working;
    }
}


Notar que el propio hilo se sincroniza y si se cumple que el hilo entra en estado suspend se llama al método wait(), esto provocará que el hilo se mantenga pausado hasta que alguien llame al método notify(); que precisamente se llama en el método resume() y se niega que el estado del hilo es suspend (suspend = false). Otro punto importante es que al tener un proceso que podría ejecutarse hasta el final de los tiempos, podriamos querer algún día detenerlo, para eso usamos el while con la variable working, que en primera instancia tendra un valor true.

Interactuar por consola con tu Thread
Lo divertido del caso era que se pudiera; mediante el teclado decirle al Thread lo que tenía que hacer, no simplemente escribirlo y no poder interactuar con el programa. Para eso, pensé en un "monitor" de entrada de teclado (Thread también por cierto) que en base a lo que escribas en el teclado defina el estado del Thread que está realizando el proceso principal. Entonces puedo escribir S (suspender), D (detener), R (reanudar) y B (salir) y con esto podré controlar los estados de mi hilo Proceso. Para este ejemplo simple solo estoy vigilando un solo Thread pero pueden ser cuantos se requieran.

Clase Entrada.java

import java.util.Scanner;

/**
 * @author ropherpanama@gmail.com
 * Esta clase esta pendiente de la entrada del usuario, la misma actua
 * como monitor de entrada por teclado y dependiendo de ello ajustara el estado
 * del Hilo al cual controla
 *
 */
public class Entrada implements Runnable {
    private Scanner sc = new Scanner(System.in);
    private String command = "";
    private Proceso p1;

    public Entrada(Proceso p1) {
        this.p1 = p1;
    }

    @Override
    public void run() {
        while (true) {
            System.out.println("Waiting input:");
            command = sc.nextLine();

            if (this.getCommand().toUpperCase().equals("S")) {
                p1.suspend();
            } else if (this.getCommand().toUpperCase().equals("R")) {
                p1.resume();
            } else if (this.getCommand().toUpperCase().equals("D")) {
                p1.setWorking(false);
                System.out.println("Fin de trabajo");
            } else if (this.getCommand().toUpperCase().equals("B")) {
                System.out.println("Saliendo");
                System.exit(0);
            } else
                System.out.println("No input");
        }
    }

    public String getCommand() {
        return command;
    }

    public void setCommand(String command) {
        this.command = command;
    }
}


Vemos que esta clase, al igual que Proceso implementa la Runnable, por ende tambien es un Thread. Este hilo va a estar pendiente de lo que escribas en el teclado y según ello actuará sobre el Thread que este monitorizando.

Ahora vamos a probar esto, creamos la clase Test.java que contiene el main y lo ponemos todo a interactuar.

Clase Test.java

public class Test {
    public static void main(String[] args) {
        Proceso p1 = new Proceso("Juana");
        p1.start();
       
        Entrada e = new Entrada(p1);
        Thread input = new Thread(e);
        input.start();
    }
}


Bien, he llamado a mi proceso principal "Juana" (no sé porqué) y le he dicho que inicie (p1.start()), luego; he creado una instancia de mi Thread monitor de entrada, para que vigile lo que escribo y opere sobre "Juana". Notar que le paso a "Juana" (p1) como argumento de su constructor. Entrada e = new Entrada(p1);
 
La salida del programa es la siguiente:

Starting Juana
Running Juana
Juana doing : 0
Waiting input:
Juana doing : 1
Juana doing : 2
Juana doing : 3
Juana doing : 4
Juana doing : 5
Juana doing : 6
Juana doing : 7
Juana doing : 8
S
Juana doing : 9

Suspending Juana
Waiting input:
R
Resuming Juana
Waiting input:
Juana doing : 10
Juana doing : 11
Juana doing : 12
Juana doing : 13
Juana doing : 14
Juana doing : 15
Juana doing : 16
B
Juana doing : 17

Saliendo


Juana inicio y se ejecutó, e inició a tirar sus números. Luego le dije Juana descanza un rato (S) y descanzó hasta que le dije continúa (R), siguió hasta el número 17 y le dije sal del programa totalmente (B)

Si te quedan dudas te invito a ver la video demostración en Youtube, pronto pongo el link.
Saludos!

viernes, 23 de agosto de 2013

Verificar estado del WIFI en android

Este es un tipo de funcionalidad que es bueno tenerla en una clase de utilidades globales (en otras palabras, en un a clase de métodos estáticos).

Aveces es necesario conocer el estado del adaptador de red WIFI, para permitirle al usuario o a la misma aplicación realizar o no un proceso crítico del flujo de ejecución.

Como lo escribí arriba hagamos una clase de utilidades, como la siguiente:

import android.content.Context;

public class SystemUtils {   
    public static boolean isWifiOn(Context context) {
        ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
        NetworkInfo ni = cm.getNetworkInfo(ConnectivityManager.TYPE_WIFI);
       
        if(!ni.isConnected()) return false; else return true;
    }
}

Nuestro método isWifiOn nos retornará un true si el WIFI está encendido; un false en caso contrario. Lo que nos permite implementar una acción dependiendo del caso en el que sea llamada la función, por ejemplo:

...

if(SystemUtils.isWifiOn(getApplicationContext()))
Toast.makeText(getApplicationContext(), "WIFI está encendido", Toast.LENGTH_LONG).show();
else
Toast.makeText(getApplicationContext(), "WIFI está apagado", Toast.LENGTH_LONG).show();
...

Noten que al ser un método estatico lo podemos llamar sin instanciar la clase SystemUtils; pues lo podemos acceder mediante un llamado directo.

Otro punto muy importante, antes de ejecutar tu aplicación asegurate de que en el AndroidManifest.xml le estás cediendo los permisos a la aplicación para que pueda verificar el estado del adaptador.

    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>

Espero les sirva, saludos!

martes, 10 de abril de 2012

Crear PDF con Java, Netbeans y iText

Atención: Estoy suponiendo que tienes un conocimiento medio de Java y que usas fluidamente Netbeans. Gracias.

En un par de pasos vamos a crear un archivo PDF en JAVA

Materiales:
1. Libreria iText (http://sourceforge.net/projects/itext/files/iText/iText5.2.0/)
   Para este ejemplo use la version 5.2.0
2. Una pequeña imagen
   Para este ejemplo use una imagen en formato PNG, puede ser cualquiera
Deberás añadir las librerías de iText a tu proyecto, para que puedas hacer uso de las clase que se detallan aquí.
Teniendo todo esto vamos a crear nuestro archivo.
Vamos a crear una clase con cualquier nombre, en mi caso yo le pondré CreatePDF y dentro de ella voy a crear un método llamado writePDF. Tambien vamos
a colocarle un método main, el esqueleto quedaria así.

public class CreatePDF
{
    public void writePDF()
    {...}

    public static void main(String args[])
    {
        new CreatePDF().writePDF();
    }
}

Luego de esto lo primero que debemos hacer es importar los Objetos que vamos a utilizar, para nuestro básico ejemplo solo debemos añadir los
siguientes
          import com.itextpdf.text.BaseColor;
    import com.itextpdf.text.Chunk;
    import com.itextpdf.text.Document;
    import com.itextpdf.text.Font;
    import com.itextpdf.text.FontFactory;
    import com.itextpdf.text.Image;
    import com.itextpdf.text.PageSize;
    import com.itextpdf.text.Paragraph;
    import com.itextpdf.text.pdf.PdfWriter;
   
    public class CreatePDF ...

   
Ahora bien dentro del método writePDF() irá toda nuestra lógica para crear nuestro documento, vamos primero a crear un bloque try/catch y dentro de
él colocaremos las siguientes líneas; las cuales iré explicando paso a paso.

            Document document = new Document(PageSize.LETTER, 80, 80,              50, 50);
      FileOutputStream salida = new                        FileOutputStream("archivo.pdf");
      PdfWriter writer = PdfWriter.getInstance(document, salida);
      writer.setInitialLeading(0);


Como todo en Java debemos tener una instancia de un objeto antes de trabajar con el, por eso debemos tener una referencia a un objeto de tipo
Document que es quien representa nuestra hoja en blanco para escribir. Con el atributo PageSize.LETTER lo que le estamos indicando es que el
documento tendrá las dimesiones de un archivo en formato CARTA (si tambien hay para los demas estandares, investígalos), acompañando lo antes mencionado
esta el valor de los margenes de nuestro documento (margenIzq, margenDer, margenArriba, margenAbajo), pueden ser los valores que gustes compañero.
Con la línea del FileOutputStream únicamente estamos creando físicamente nuestro archivo en disco, allí iran todos nuestros cambios al documento.
Luego necesitamos tener una instancia de quien escribira nuestros cambios y darle su punto de inicio para que pueda escribir, (writer.setInitialLeading(0);).

Hecho todo esto solo nos queda ir "escribiendo" dentro de nuestro papel en blanco que ya hemos preparado, vamos a añadir dos párrafos sencillos juntos a
una imagen.

               Paragraph paragraph = new Paragraph();
      paragraph.add("Primera linea del documento");
      paragraph.setAlignment(Paragraph.ALIGN_CENTER);


Para escribir texto usamos la clase Paragraph, como ves tiene un metodo add en el que puedes escribir lo que desees...
esta clase tiene muchos métodos interesantes, como el que vemos aquí paragraph.setAlignment(Paragraph.ALIGN_CENTER) que como lo
adivinaste es para alinear en donde queramos.

            Image image = Image.getInstance("imagen.png");
           image.scaleToFit(150, 150);
           image.setAlignment(Chunk.ALIGN_CENTER);


Para colocar imégenes debemos instanciar un objeto de tipo Image, darle la ubicacion de nuestra imagen al constructor, darle el tamaño que
gustemos y alinearla.

            Paragraph paragraph_2 = new Paragraph();
            paragraph_2.setFont(new Font(FontFactory.getFont("Courier", 12, Font.BOLD, BaseColor.ORANGE)));
            paragraph_2.add("Ultima linea del documento");
            paragraph_2.setAlignment(Paragraph.ALIGN_LEFT);


En este parrafo lo unico que hemos hecho diferente es darle una fuente y color especifico a nuestro texto, hay otras formas de hacerlo
incluso si tienes fuentes extrañas instaladas en su carpeta Fonts de Windows puedes crear una nueva fuente a partir de esa, ya que por lo
general las fuentes "extrañas" no las reconoce, hagan la prueba y me comentan (si si si, tengo la solución si les llega a pasar..)

Antes de añadir todo nuestro contenido debemos abrir el documento para poder usarlo:
            document.open();
luego ir añadiendo en el orden en que queremos que aparezcan todos los checheres que hemos creado
               document.add(paragraph);
      document.add(image);
      document.add(paragraph_2);

y por logica... si abres algo, cierralo.
            document.close();

Eso es todo! Luego de que lo corras deberás tener en tu carpeta de proyecto tu archivo PDF.
Saludos, para dudas a la orden!!!