Posts Tagged ‘java’

  • Como escribir un MOD_REWRITE en minutos

    0

    La verdad es que no estoy tratando de reinventar la rueda, solo trato de que mi framework (java) este up to date. Hace un tiempo un ex-coworker me conto sobre el MOD_REWRITE Apache Webserver para tener urls un poco mas elegantes que algo como esto (q?u=w2&a=w3&…). Segun el (experto) son muchos mejores para los spiders que indexan paginas y mas atractivas para los usuarios que las leen.
    Como mi fuerte es Java y no PHP decidi hace mi propia version de MOD_REWRITE. Primero antes de poner una linea de codigo obviamente googlee un poco para ver que habia y me encontre con un snippet escrito por Paul Tuckey aca. Paul hizo un laburo excelente, pero era demasiado para mi aplicacion, yo necesitaba algo mucho mas simple entonces tome los conceptos de su software y los aplique al mio.

    1. Lo primero que pense fue que deberia haber una referencia entre la URL nice looking y la URL real de la pagina con contenido dinamico que queremos mostrar. En mi caso era un Blog software, por lo cual agregue a mi tabla POST un campo nuevo llamado title_url.

    2. Ahora era el turno de algun tipo de Facade entre la URL virtual y la real, para eso utilice un Servlet Filter. Aca el codigo:

    public class PostFilter implements Filter {

    private Map<String, String> cache;
    private Pattern pattern;

    /**
    * Inits the class
    */
    public void init(FilterConfig config) throws ServletException {
    this.cache = new HashMap<String, String>();
    this.pattern = Pattern.compile(“/post/(?!images|myservlet)”);  // the regex string to filter all /post/* requests
    }

    /**
    * Main filter method
    */
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
    try {
    HttpServletRequest req = (HttpServletRequest) request;
    String uri = req.getRequestURI();
    if (this.match(uri)) {
    String titleUrl = uri.substring(uri.lastIndexOf(‘/’) 1, uri.length());
    String url = null;
    if (cache.containsKey(titleUrl)) {
    url = cache.get(titleUrl);
    } else {
    url = this.createUrlForPost(titleUrl);
    }
    req.getRequestDispatcher(url).forward(request, response);
    return;
    }
    chain.doFilter(request, response);
    } catch (Exception e) {
    e.printStackTrace();
    response.getWriter().write(“ERROR”);
    }
    }

    /**
    * Returns the real url for this post
    * @param titleUrl
    * @return
    * @throws Exception
    */
    private String createUrlForPost(String titleUrl) throws Exception {
    String postId = this.queryPostIdByTitleUrl(titleUrl);
    String url = “../myservlet?key=value&key1=value1&etc,etc&id=” postId;
    this.cache.put(titleUrl, url);
    return url;
    }

    /**
    * Match if the url is part of a post
    * @param uri
    * @return
    */
    private boolean match(String uri) {
    Matcher matcher = pattern.matcher(uri);
    boolean found = false;
    while (matcher.find()) {
    found = true;
    }
    return found;
    }

    /**
    * Inits the class
    */
    private void queryPostIdByTitleUrl(String titleUrl) throws Exception {
    // some code to access to the field of the database
    return postid;
    }

    3. Ahora el siguiente paso es poner el filtro en el web.xml.

    <filter>
    <filter-name>PostFilter</filter-name>
    <filter-class>PostFilter</filter-class>
    </filter>

    <filter-mapping>
    <filter-name>PostFilter</filter-name>
    <url-pattern>/post/*</url-pattern>
    </filter-mapping>

    4. No hay mas que eso. Que lo disfruten :)

  • Convenciones y Best Practices para Java

    0

    Este es un recompilado de Best Practices y Convenciones que trato de aplicar diariamente en el codigo que escribo. Quiza es util para ustedes tambien. Hay que recordar que el codigo trabaja con logica matematica, pero los developers no por eso es importante que el codigo no solo sea legible para vos, sino para todo el grupo que trabaja con vos. Simplemente imaginate tratar de modificar codigo que esta escrito en 1 linea OLPL (one line programming language) o metodos de 1000 lineas, es realmente tedioso.Las convenciones en Java son diferentes de C or C#. Voy a postear varias convenciones que me gusta aplicar, pero para ver todas las convenciones de Java podes ir aca.
    Las convenciones son necesarias para mantener similitud en el codigo y para ser legible por cualquier miembro de tu grupo, incluso vos mismo. Quiza tu grupo quiera hacer sus propias convenciones, pero yo te aconsejo que sigas los lineamientos de Sun ya que si algun dia cambias de empresa y ellos usan las convenciones oficiales, vas a odiarlos ya que tenes que adaptarte a algo nuevo y no tenes control de nada.

    1. Class names

    Basicamente Sun dice que las classes tienen que ser Camel Case empezando la primera letra en mayuscula y siguiendo con minusculas hasta el cambio de palabra donde volves a aplicar una mayuscula.
    Las classes Java usualmente representan cosas abstractas o concretas, lo que significa que si creas una clase que representa un hospital, no la podes llamar Htal!! es un Hospital !.

    Hospital
    Patient
    RequestDispatcher
    StringUtility
    

    2. Nombres de Variable

    Lucho dia a dia con mis compañeros de trabajo por los nombres de las variables. Parecidos a los nombres de clase, las variables son super importantes ya que son unidades que nos permitiran intuir y entender que hace el programa. La convención Java para las variables es Camel Case tambien pero la primera letra es minuscula.

    Veamos el siguiente codigo.

    double up = myBean.getUnitPrice();
    int q = myBean.getQuantity();
    double t = up * q;
    

    Este caso es muy simple, pero imaginemos que quantity, unit price y total son usados en un metodo de 100 lineas de codigo (horrible pero cierto). Seria feo ver esta linea en medio de todo eso, no muchos entenderian esto…

    int dp = 20; // discount percentage
    if (q &gt; m) {
      t = t * dp / 100;
    }
    

    La verdad que si me toca arreglar o modifcar este metodo me voy a querer matar. Tener que buscar que significa t, q y m es tedioso sumando la perdida de tiempo.

    Hagamos algo asi…

    double unitPrice = myBean.getUnitPrice();
    int quantity = myBean.getQuantity();
    double total = unitPrice * quantity;
    int discountPercentage = 20;
    if (quantity && maxAllowed) {
      total = total * discountPercentage / 100;
    }
    

    3. Condicionales

    Tengo un par de ejemplos con esto, algunos tontos otros no tanto.

    3.1. No usar extra codigo

    if (latoya.isInsane() ) {
      return this;
    } else {
      return that;
    }
    

    La segunda parte (else) es totalmente una perdida de tiempo tuyo y del procesador ya que no hay posibilidad de ir al ELSE si el primer IF evalua a TRUE. Yo haria algo asi…

    if (latoya.isInsane() ) {
      return this;
    }
    return that;
    

    3.2. Primera condicion encontrada

    if (a &lt; b || b &gt; c) {
      this.execute();
    }
    

    Si la primera condicion es valida la segunda nunca va a ser evaluada. Si usas | en vez de || no importa lo que pase, la segunda condicion si va a ser evaluada. Hay casos donde estos operadores son necestarios, pero la realidad muestra que son los menos. El codigo default deberia ser usando doble pipe ||.

    Shorthand</strong><br><br><span style=”FONT-FAMILY: Courier New”>&nbsp;&nbsp;&nbsp; String a = (y == z) ? “this” : that;</span><br><br>Me encanta este shorthand del IF ELSE, pero algunas veces se suele abusar y ahi empieza el <strong>OLPL </strong>(one line programming language) como esto…<br><br><span style=”FONT-FAMILY: Courier New”>&nbsp;&nbsp;&nbsp; String a = (y == z) ? (x &gt; m) ? true : a &lt; t : (list.size() &gt; x) ……..</span><br><br>Por favor, eviten hacer cosas asi, duelen los ojos solo de mirarlo.<br><strong><br>4. Retorno al inicio</strong><br><br>Un ex jefe mio me odiaba cada vez q yo hacia esto, pero realmente me parece mucho mas claro.<br><br><span style=”FONT-FAMILY: Courier New”>&nbsp;&nbsp;&nbsp; if (!var.isSomething()) return;</span><br><span style=”FONT-FAMILY: Courier New”>&nbsp;&nbsp;&nbsp; String a = this.afunction();</span><br><span style=”FONT-FAMILY: Courier New”>&nbsp;&nbsp;&nbsp; more code….</span><br><span style=”FONT-FAMILY: Courier New”>&nbsp;&nbsp; &nbsp;more code….</span><br><span style=”FONT-FAMILY: Courier New”>&nbsp;&nbsp; &nbsp;more code….</span><br><br>El preferia hacer cosas asi, pero yo creo que es menos claro cuales son las condiciones de salida de este statement ya que tenemos que ir al final del codigo para verlo.<br><br><span style=”FONT-FAMILY: Courier New”>&nbsp;&nbsp;&nbsp; if (var.isSomething()) {</span><br><span style=”FONT-FAMILY: Courier New”>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; String a = this.afunction();</span><br><span style=”FONT-FAMILY: Courier New”>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; more code…. &nbsp;</span><br><span style=”FONT-FAMILY: Courier New”>&nbsp;&nbsp;&nbsp; } else {</span><br><span style=”FONT-FAMILY: Courier New”>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return;</span><br><span style=”FONT-FAMILY: Courier New”>&nbsp;&nbsp;&nbsp; }</span><br><br>Bueno, esta es la primera entrega de mis best practices en Java, stay tuned!

  • Servicios Java en Linux

    0

    Este articulo habla acerca de como implementar un servicio Java en Linux usando Apache Commons Daemon.Commons Daemon es la API de Apache para correr procesos en Linux o Windows. En el articulo de hoy vamos a ver como implementar un simple servicio desde la JVM, el codigo Java y el Script del Linux Daemon.

    Actualmente estoy trabajando con un linux Ubuntu Server 7.10 y Java 1.6. Como primer paso tenemos que instalar Java y Commons Daemon, a continuacion los comandos.

    1. Para instalar el java SDK hacemos..

     $ sudo apt-get install sun-java6-jdk

    Esto instala el JDK de Sun (Si queres podes instalar otra distrubucion o version, como por ejemplo icetea open JDK.

    2. Instalar JSVC (Apache Commons Daemon)

     $sudo apt-get install jsvc

    JSVC es el binario que permite correr a aplicaciones Java como procesos en Linux.

    3. El codigo Java. Aqui debemos implementar la interfaz Daemon el cual sera llamado por el servicio jsvc. Yo ODIO el vi, por eso uso nano como editor en el linux. La idea es teminar con codigo java asi que podes usar el editor que prefieras.

    import org.apache.commons.daemon.Daemon;
    import org.apache.commons.daemon.DaemonContext;
    
    public class Test implements Daemon {
    
    @Override
    public void init(DaemonContext arg0) throws Exception {
      System.out.println("starting app...");
      while (true) {
        System.out.println(System.currentTimeMillis());
        Thread.sleep(1000);
      }
    }
    
    @Override
    public void destroy() {
      System.out.println("destroy called");
    }
    
    @Override
    public void start() throws Exception {
      System.out.println("start called");
    }
    
    @Override
    public void stop() throws Exception {
      System.out.println("stop called");
    }
    }

    4. Compilar el codigo Java, como todos ya saben supongo tienen que tener el JAR de commons-daemon en el classpath, lo pueden encontrar aca.

     javac -cp .:commons-daemon-jar Test.java

    5. Hay que generar un shell script que va a actuar como linux daemon.

     nano /etc/init.d/testd

    Esto abre el editor parecido al VI, el codigo a continuacion:

    echo "Setting enviroment variables..."
    export JAVA_HOME=/usr/lib/jvm/java-6-sun-1.6.0.03
    export PATH=$PATH:$JAVA_HOME/bin
    
    DAEMON_HOME=/usr/bin
    PID_FILE=/home/myuser/test.pid
    HOME=/home/myuser
    USER=myuser
    RETVAL=0
    TMP_DIR=/var/tmp
    CLASSPATH=.:/usr/share/java/commons-daemon.jar
    $JAVA_HOME/lib/tools.jar\
    
    case "$1" in
     start)
    
     echo "Starting Daemon Test"
     $DAEMON_HOME/jsvc \
     -user $USER \
     -home $JAVA_HOME \
     -Djava.io.tmpdir=$TMP_DIR \
     -pidfile $PID_FILE \
     -outfile $HOME/log.out \
     -errfile $HOME/log.err \
     -cp $CLASSPATH \
     Test
    
     echo "test daemon started OK."
     exit $?;;
    
     stop)
     echo "Stopping Test..."
     $DAEMON_HOME/jsvc \
     -stop \
     -pidfile $PID_FILE \
     Test
     echo "test stopped"
     exit $?
     ;;
    
     *)
     echo "Usage test start/stop"
     exit 1;;
    esac
    

    5. Este es el final donde hacemos correr nuestro daemon de la siguiente manera

     /etc/init.d/testd start

    6. Para detener el daemon ejecutamos el siguiente comando:

     /etc/init.d/testd stop

    Eso es todo, que lo disfruten.

Page 9 of 9« First...«56789