Category Archives: Uncategorized

Ejemplo de CountDownLatch

Published / by Renan Huanca / Leave a Comment

Hola Amigos, esta semana tengo un simple ejemplo de uso de la clase CountDownLatch.

Esta clase simplemente nos ayuda a sincronizar operaciones dentro de varios threads que necesiten ejecutarse en un momento dado.

El siguiente ejemplo muestra la creación de 50 threads. Como verán, dentro del método run() hay una porción de código que llama a la funcion await(). Esto ayuda a que cada thread no ejecute el siguiente segmento de código hasta que la señal del CountDownLatch sea lanzado.

El código fuente lo pueden encontrar en acá.
Mas información la pueden encontrar en:

import java.util.concurrent.CountDownLatch;

public class CountDownLatchExample {
	
	public static void main(String... args) {
		// Instantiating countdownlatch class.
		CountDownLatch countDown = new CountDownLatch(1);
		System.out.println("Creating threads...");
		
		// going to create 50 threads.
		for(int i=0;i<50;i++) {
			Worker worker = new Worker(countDown, "Worker #"+i);
			new Thread(worker).start();
		}
		
		// Now start all threads at the same time.
		countDown.countDown();
		
	}
	
	/**
	 * This class is just a simple dummy thread.
	 */
	private static class  Worker implements Runnable {
		CountDownLatch startLatch;
		String name;
		
		public Worker(CountDownLatch startLatch, String name) {
			super();
			this.startLatch = startLatch;
			this.name = name;
		}

		public void run() {
			try {
				// Going to wait until the signal is being fired.
				this.startLatch.await();
			} catch (InterruptedException e) {
				throw new RuntimeException(e);
			}
			System.out.println("Running " + name+".");
		}
	}
}

Custom (Personalizado) XML DataSource con JasperReports

Published / by Renan Huanca / Leave a Comment

Hola amigos,

Aca un ejemplo muy sencillo de como implementar las interfaces JRDataSource y JRRewindableDataSource de JasperReports para iterar un documento xml.

Clase CustomXMLDataSource

Como verán el constructor de la clase recibe, una instancia de la interface (XML) Document, luego extrae el nodo raiz y después obtiene la lista de los nodos hijos.

Para navegar por la lista de nodos se usa una variable llamada index, cuyo valor inicial es -1 para que la primera vez que se llame al método next(), este apunte al primer elemento de la lista.

El método getFieldValue usa los atributos del nodo actual para ser retornado hacia afuera. Para esto se usa el description del JRField. Lo que me gusta de este metodo es que uno acá puede implementar cualquier lógica que uno desee para obtener información de cualquier tipo de fuente de datos. Acá se podría aplicar cosas mas complejas como Xpath, o talvez hacer algo simple como buscar un nodo basado en el JRField. Alguien me comento que usar XPath puede ser un poco mas lento, es por eso que esta interface es muy importante para nosotros.

El método moveFirst es el que se encarga hacer que data source vuelva al primer nodo. Esta parte me gusto mucho, por que vi que por defecto el JRDataSource de JasperReport no implementa este metodo, seguro para hacerlo mas genérico al momento de trabajar con fuentes de datos que no sean tan fácil de manejar como una lista:).

Pruebas de unidad y código fuente

En las pruebas de unidad podrán apreciar varios casos de uso de la clase.Como ser: utilizando un xml que tiene un solo nodo, cuando son varios, etc.

El código fuente esta disponible en: https://github.com/rhuanca/examples/tree/master/jasper-reports

Saludos,
Renan

package renidev.examples.jaspereports;

import org.w3c.dom.Document;
import org.w3c.dom.NodeList;

import net.sf.jasperreports.engine.JRDataSource;
import net.sf.jasperreports.engine.JRException;
import net.sf.jasperreports.engine.JRField;
import net.sf.jasperreports.engine.JRRewindableDataSource;

/**
 * This is a sample custom data source for xml.
 * @author Renan Huanca
 *
 */
public class CustomXMLDataSource implements JRDataSource, JRRewindableDataSource {

	private NodeList childNodes;
	private int index;
	
	public CustomXMLDataSource(Document document) {
		// Note: document.getFirstChild() will return the root node.
		this.childNodes = document.getFirstChild().getChildNodes();
		this.index = -1;
	}

	/**
	 * Implementation of the getFieldValue method.
	 * In this case this method is extracting the value 
	 * from the note's attributes.
	 */
	public Object getFieldValue(JRField jrField) throws JRException {
		String nodeName = jrField.getDescription();
		return childNodes.item(index).getAttributes().getNamedItem(nodeName).getTextContent();
	}

	public boolean next() throws JRException {
		++this.index;
		return this.index < childNodes.getLength();
	}

	public void moveFirst() throws JRException {
		this.index = -1;
	}
}
package renidev.examples.jasperreports;

import static org.junit.Assert.*;
import org.junit.Test;
import net.sf.jasperreports.engine.JRException;
import net.sf.jasperreports.engine.JRField;
import net.sf.jasperreports.engine.design.JRDesignField;
import renidev.examples.jaspereports.CustomXMLDataSource;


public class CustomXMLDataSourceTest {
	
	@Test
	public void single_case() throws JRException{
		String xml ="";
		CustomXMLDataSource dataSource = new CustomXMLDataSource(SimpleDocumentBuilder.buildDocument(xml));
		assertFalse(dataSource.next());
	}
	
	@Test
	public void one_child_node() throws JRException{
		String xml ="";
		CustomXMLDataSource dataSource = new CustomXMLDataSource(SimpleDocumentBuilder.buildDocument(xml));
		assertTrue(dataSource.next());
		assertEquals("carlos", dataSource.getFieldValue(createField("name")));
		assertFalse(dataSource.next());
	}
	
	@Test
	public void two_child_nodes() throws JRException{
		String xml =
				"" +
					"" +
					"" +
				"";
		CustomXMLDataSource dataSource = new CustomXMLDataSource(SimpleDocumentBuilder.buildDocument(xml));
		JRField nameField = createField("name");
		
		// reading data data
		assertTrue(dataSource.next());
		assertEquals("carlos", dataSource.getFieldValue(nameField));
		assertTrue(dataSource.next());
		assertEquals("gonzalo", dataSource.getFieldValue(nameField));
		
		// checking there is no more data 
		assertFalse(dataSource.next());
	}
	
	@Test
	public void two_child_nodes_and_two_attributes() throws JRException{
		String xml =
				"" +
					"" +
					"" +
				"";
		CustomXMLDataSource dataSource = new CustomXMLDataSource(SimpleDocumentBuilder.buildDocument(xml));
		JRField nameField = createField("name");
		JRField fromField = createField("from");
		
		// reading data data
		assertTrue(dataSource.next());
		assertEquals("carlos", dataSource.getFieldValue(nameField));
		assertEquals("work", dataSource.getFieldValue(fromField));
		assertTrue(dataSource.next());
		assertEquals("gonzalo", dataSource.getFieldValue(nameField));
		assertEquals("raquet", dataSource.getFieldValue(fromField));
		
		// checking there is no more data 
		assertFalse(dataSource.next());
	}

	
	@Test
	public void two_child_nodes_and_rewind() throws JRException{
		String xml =
				"" +
					"" +
					"" +
				"";
		
		CustomXMLDataSource dataSource = new CustomXMLDataSource(SimpleDocumentBuilder.buildDocument(xml));
		JRField nameField = createField("name");
		
		// bypassing two nodes
		assertTrue(dataSource.next());
		assertTrue(dataSource.next());
		
		// checking there is no more data 
		assertFalse(dataSource.next());
		
		// rewind the data source
		dataSource.moveFirst();
		
		// reading data data
		assertTrue(dataSource.next());
		assertEquals("carlos", dataSource.getFieldValue(nameField));
		assertTrue(dataSource.next());
		assertEquals("gonzalo", dataSource.getFieldValue(nameField));
	}
	
	public JRField createField(String description){
		JRDesignField field = new JRDesignField();
		field.setDescription(description);
		return field;
	}
}

Simple (DOM) DocumentBuilder para Java

Published / by Renan Huanca / Leave a Comment

Hola Amigos,

Acá comparto una clase que ayuda a crear una instancia de un java DOM Document.

Estas son las características de la clase:

  1. Te quita todo el tedioso trabajo de hacer explícitamente el catch de las excepciones, haciendo que tu código sea mas legible y entendible.
  2. Las excepciones son manejadas con un solo handler, haciendo que puedas mejorar la clase aumentar varios builders y manejar las excepciones en un solo método.
  3. También pueden apreciar que la instancia del DocumentBuilderFactory es inicializado estáticamente.

Luego mas abajo podrán ver las pruebas de unidad con solo casos mas simple y el manejo de una excepción.

Si desean bajar el código, este esta disponible en: https://github.com/rhuanca/XMLUtilities

package renidev.utils.xml;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import org.w3c.dom.Document;
import org.xml.sax.SAXException;
import org.xml.sax.SAXParseException;

/**
 * This class helps to create a instance of a DOM document instance
 * simplifying the way to create it.
 * @author Renan Huanca
 */
public class SimpleDocumentBuilder {
    private static DocumentBuilder documentBuilder;

    static {
        try {
            documentBuilder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
        } catch (ParserConfigurationException e) {
            throw new RuntimeException("Unable to get document builder. - "+ e.getMessage(), e);
        }
    }
    
    /**
     * Allow to create a DOM Document instance with the given parameter.
     * 
     * @param xml
     * @return
     */
    public static Document buildDocument(String xml) {
        Document doc = null;
        try {
            doc = documentBuilder.parse(new ByteArrayInputStream(xml.getBytes()));
        } catch (Exception e) {
            handleException(e);
        } 
        return doc;
    }

    /**
     * Allow to create a DOM Document instance with the given parameter.
     * @param stream
     * @return
     */
    public static Document buildDocument(InputStream stream) {
        Document doc = null;
        try {
            doc = documentBuilder.parse(stream);
        } catch (Exception e) {
            handleException(e);
        } 
        return doc;
    }
    
    public static void handleException(Exception e){
        if(e instanceof IOException) {
            throw new RuntimeException("Unable to read xml - " + e.getMessage(), e);
        } else if (e instanceof SAXParseException) {
            SAXParseException exception = (SAXParseException) e;
            throw new RuntimeException("Unable to parse xml - Line: " + 
                    exception.getLineNumber() + " - " + e.getMessage(), e);
        } else if ( e instanceof SAXException) {
            throw new RuntimeException("Unable to parse xml - " + e.getMessage(), e);
        } else {
            throw new RuntimeException(e);
        }
    }
}

package renidev.utils.xml;

import org.junit.Test;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import static org.junit.Assert.*;

public class SimpleDocumentBuilderTest {

    @Test
    public void one_node(){
        String xml = "hello world";
        Document doc = SimpleDocumentBuilder.buildDocument(xml);
        Node dataNode = doc.getFirstChild();
        assertEquals(1, dataNode.getChildNodes().getLength());
        assertEquals("hello world", dataNode.getTextContent());
    }
    
    @Test
    public void one_level(){
        String xml = "hello world";
        Document doc = SimpleDocumentBuilder.buildDocument(xml);
        Node dataNode = doc.getFirstChild();
        assertEquals(1, dataNode.getChildNodes().getLength());
        assertEquals("hello world", dataNode.getFirstChild().getTextContent());
    }
    
    @Test 
    public void test_exception(){
        String xml = "hello world";
        try {
            @SuppressWarnings("unused")
            Document doc = SimpleDocumentBuilder.buildDocument(xml);
        } catch (RuntimeException e) {
            assertEquals("Unable to parse xml - Line: 1 - XML document structures must start and end within the same entity.", e.getMessage());
            return;
        }
        fail("No exception was throw");
    }
}

Conexiones de Based de Datos Multiples con Spring 3

Published / by Renan Huanca / 7 Comments on Conexiones de Based de Datos Multiples con Spring 3

Hola amigos, disculpen por el tiempo que no postee, en mi trabajo me tenían muy ocupado.

Preliminar

Mostrare como se configura Spring para poder conectarse a múltiples bases de datos usando Spring 3.

Archivo de contexto de Spring

Primeramente definimos las conexiones disponibles en el archivo de contexto de Spring.



    
    
    ...
    
	
        
        
        
        
    

	
    
        
        
        
        
    
    ...

Dao para acceder al datasource de projectos.

Básicamente utilizaremos el patrón de interfase, implementación e inversión de control.

package edu.renan.samples;

import javax.sql.DataSource;
/**
 * To manage projects in our company.
 */
public interface ProjectsDao {

    /**
     * Sets a notes data source for this dao.
     * @param projectDataSource
     */
    public void setProjectsDataSource(DataSource projectDataSource);

    /**
     * list all projects...(je je this is just an example)
     */
    public Collection listAllProjects();
}
package edu.renan.samples;

import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Component;
import javax.sql.DataSource;
import java.util.Date;

@Component("projectsDao")
public class ProjectsDaoImpl implements ProjectsDao {

    private JdbcTemplate jdbcTemplate;

    @Autowired
    public void setProjectsDataSource(@Qualifier("projectsDataSource") DataSource projectsDataSource) {
        this.jdbcTemplate = new JdbcTemplate(projectsDataSource);
    }
	
    public Collection listAllProjects(){
        return this.jdbcTemplate.query( "select * from projects", new ProjectMapper());
    }
}

Tengo que resaltar que aqui estoy utilizando la anotación @Qualifier. Esta anotación nos permite explícitamente indicar que DataSource utilizar. y Listo!!!.

Bueno amigos eso seria todo por hoy, abajo pueden encontrar algunos links a recursos.

Recursos

Hola Mundo con Spring BlazeDS y Flex

Published / by Renan Huanca / 4 Comments on Hola Mundo con Spring BlazeDS y Flex

Hola amigos, acá comparto un ejemplo de como desarrollar un “Hola mundo” con Spring BlazeDS y con Flex.

Vamos directo al código 🙂

Maven

Las principales cosas que definimos en el archivo maven son:

  1. Dependencias JSP/Servlet.
  2. Dependencias para el Spring framework.
  3. Dependencias para el Spring BlazeDS.
  4. Plugin para compilar java con 1.5 que tiene soporte para anotaciones.

    ...

    
    
        3.0.0.RELEASE
    

    
    
        ...
        
        
            javax.servlet
            servlet-api
            2.5
            provided
        

        
            javax.servlet.jsp
            jsp-api
            2.1
            provided
        
        
        
        
            org.springframework
            spring-webmvc
            ${org.springframework.version}
        
        
            org.springframework
            spring-aop
            ${org.springframework.version}
        
        
            org.springframework.flex
            spring-flex
            1.0.3.RELEASE
        

        
        
            com.adobe.blazeds
            blazeds-core
            3.2.0.3978
        
        
            com.adobe.blazeds
            blazeds-proxy
            3.2.0.3978
        
        
            com.adobe.blazeds
            blazeds-opt
            3.2.0.3978
        
        
            com.adobe.blazeds
            blazeds-remoting
            3.2.0.3978
        

        ...
    
    
        helloblazeds
        
            
                org.apache.maven.plugins
                maven-compiler-plugin
                
                    1.5
                    1.5
                
            
            ...    
        
    

web.xml

En el web.xml tenemos:

  1. Definición de un Filtro para soportar caracteres UTF8.
  2. Mapeo de la servlet de Spring para manejar cualquier pedido que pase por /messagebroker/*.



    Hello World with SpringBlazeDS

    
    
        encoding-filter
        
            org.springframework.web.filter.CharacterEncodingFilter
        
        
            encoding
            UTF-8
        
    

    
        encoding-filter
        /*
    

    
    
    
        spring-flex
        org.springframework.web.servlet.DispatcherServlet
        
            contextConfigLocation
            /WEB-INF/flex-servlet-context.xml
        
        1
    

    
        spring-flex
        /messagebroker/*
    

    
    
        index.html
    

flex-servlet-context.xml, services-config.xml y remoting-config.xml

El flex-servlet-context.xml es bien sencillo. Solo le indicamos a Spring que paquete escanear para buscar clases anotadas y la definición del bean MessageBroker para la integración con Flex.



    
    

El services-config.xml sirve para definir los canales y servicios que serán soportados. Véase también que en el canal estamos indicando como vienen los pedidos, en este caso “/messagebroker/amf”



    
        
        
           
        
    

    
        
            
        
    
    
        
            
                [BlazeDS]
                false
                false
                false
                false
            
            
                Endpoint.*
                Service.*
                Configuration
            
        
    
    
        
            false
        
    

En el remoting-config.xml definimos el adaptar java para AMF.



    
        
    
    
        
    

Clase SayHello

La siguiente clase esta anotada como servicio y también como destinación remota para AMF 🙂

package test.flex;

import java.io.*;
import java.util.List;
import org.springframework.flex.remoting.RemotingDestination;
import org.springframework.stereotype.Service;

@Service("SayHello")
@RemotingDestination
public class SayHello {

    public String hello(){
        return "Hola Mundo";
    }
}

Finalmente el código en Flex 🙂

En la aplicación Flex tenemos:

  1. Definición de object RemoteObject.
  2. Un botón pulsante para llamar al metodo hello().
  3. Definición de dos funciones flex para manejar la respuesta en caso de éxito y fallo de la llamada.




 


 

    
    		

Escaneando anotaciones con Spring

Published / by Renan Huanca / 2 Comments on Escaneando anotaciones con Spring

Hola Amigos, acá comparto un poco de código que escribí esta semana.

El Problema

Esta semana estaba trabajando con AMF, mi problema era listar las classes que estaban anotadas con la anotación @RemotingDestination, para luego poder listarlas en una consola. (Con el objetivode mostrar los servicion AMF disponibles en el servidor)

Aca un ejemplo de una clase anotada con @RemotingDestination

package some.good.packague.to.work; // 🙂

import org.springframework.flex.remoting.RemotingDestination;
import org.springframework.stereotype.Service;

@Service("userService")
@RemotingDestination
public class UserService{

    public String getUserName(String userId) {
        .....
        return "The best name in the world :)";
    }

}

La Solución

Primeramente estaba viendo Javassist, pero al final me quede con una solución con Spring.

El ejemplo lo encontré el blog de Java Chimaera, pero le hice algunas modificaciones para que ahora soporte buscar clases tanto en linux como en windows.

El Código

package yep.this.is.a.very.good.package;

import org.springframework.core.io.Resource;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.core.io.support.ResourcePatternResolver;
import org.springframework.core.type.classreading.MetadataReader;
import org.springframework.core.type.classreading.MetadataReaderFactory;
import org.springframework.core.type.classreading.SimpleMetadataReaderFactory;
import org.springframework.core.type.filter.TypeFilter;
import org.springframework.core.type.filter.AnnotationTypeFilter;
import org.springframework.util.ClassUtils;

import java.util.Set;
import java.util.HashSet;
import java.io.IOException;

/**
 * This class is a adaptation of:
 *
 *    http://java-chimaera.blogspot.com/2008/10/scanning-classpath-annotated-classes.html
 */
/**
 * @author Renan Huanca
 * @since Apr 16, 2010 9:52:12 PM
 */
public class AnnotatedClassFinder {
    private String basePackage;
    private ResourcePatternResolver resourceResolver = null;
    private MetadataReaderFactory metadataReaderFactory = null;
    private TypeFilter annotationFilter = null;
    
    public AnnotatedClassFinder(String basePackage) {
        this.basePackage = basePackage;
        this.resourceResolver = new PathMatchingResourcePatternResolver(
                Thread.currentThread().getContextClassLoader());
        this.metadataReaderFactory = new SimpleMetadataReaderFactory();
    }

    public static AnnotatedClassFinder getInstance(String basePackage){
        return new AnnotatedClassFinder(basePackage);
    }

    public Set findByAnnotation(Class annotation) {
        this.annotationFilter = new AnnotationTypeFilter(annotation);
        Set annotatedClasses = new HashSet();
        /*
        * First of all we load all resources that are under a specific package by using a ResourcePatternResolver.
        * By doing so we will use class files as simple resources without passing
        * by the ClassLoader which can for example cause the execution of a static initialization block.
        * It resolves also transparently resources in jars.
        */
        String candidateClassesLocationPattern = "classpath*:" + basePackage + "/**/*.class";
        Resource[] resources = null;
        try {
            resources = resourceResolver.getResources(candidateClassesLocationPattern);
        } catch (IOException e) {
            throw new RuntimeException(
                    "An I/O problem occurs when trying to resolve ressources matching the pattern : "
                            + candidateClassesLocationPattern, e);
        }

        /*
        * then we proceed resource by resource, using a MetadataReaderFactory to create
        * MetadataReader wich hides the ASM related interface and complexity.
        *
        */
        for (Resource resource : resources) {
            MetadataReader metadataReader = null;
            try {
                metadataReader = this.metadataReaderFactory.getMetadataReader(resource);

                if (this.annotationFilter.match(metadataReader, metadataReaderFactory)) {

                    /*
                    * the AnnotationMetadata is a simple abstaction of the informations
                    * that holds the annotation
                    */
                    String className = convertResourceToClassName(resource, basePackage);
                    try {
                        annotatedClasses.add(ClassUtils.forName(className));
                    } catch (Exception e) {
                        throw new RuntimeException("problems occurs when trying to load the annotated class : " + className, e);
                    }
                }
            } catch (IOException e) {
                throw new RuntimeException("An I/O problem occurs when trying to process resource : " + resource, e);
            }
        }

        return annotatedClasses;
    }

    static String convertResourceToClassName(Resource resource, String basePackage) throws IOException {
        String path = resource.getFile().getPath();
        String pathWithoutSuffix = path.substring(0, path.length() - ClassUtils.CLASS_FILE_SUFFIX.length());
        String relativePathWithoutSuffix = "";
        if(System.getProperty("file.separator").equals("\\")) {
            relativePathWithoutSuffix = pathWithoutSuffix.substring(pathWithoutSuffix.indexOf(basePackage.replace('/', '\\')));
            relativePathWithoutSuffix = relativePathWithoutSuffix.replace('\\', '/');
        } else if(System.getProperty("file.separator").equals("//")) {
            relativePathWithoutSuffix = pathWithoutSuffix.substring(pathWithoutSuffix.indexOf(basePackage));
        } else {
            throw new RuntimeException("File separator is not recognized");
        }

        // taking out extra \ or /
        relativePathWithoutSuffix = relativePathWithoutSuffix.substring(1);

        return relativePathWithoutSuffix.replace('/', '.');
    }
}

Como llamarlo?

AnnotatedClassFinder finder = AnnotatedClassFinder.getInstance("/the/package/you/want/to/search");
Set classes = finder.findByAnnotation(RemotingDestination.class);

Convertir PDF a SWF con AIR 2 beta

Published / by Renan Huanca / 4 Comments on Convertir PDF a SWF con AIR 2 beta

Introducción

Hola Amigos, acá comparto una la solución a un problema que tuve esta semana. Se trata de convertir un archivo PDF al formato flash SWF.

Aca un resumen de los problemas:

  1. No existe (al momento) una forma nativa dentro de AIR para convertir un archivo pdf a swf, entonces tuve que hacer la llamada al comando pdf2swf.exe (SWFTools) desde AIR
  2. La opcion de ejecutar comandos de linea solo esta disponible en Adobe AIR 2 Beta (al momento), entonces me anime a usar la versión beta

El código

import __AS3__.vec.Vector;

import flash.desktop.NativeProcess;
import flash.desktop.NativeProcessStartupInfo;
import flash.events.IOErrorEvent;
import flash.events.NativeProcessExitEvent;
import flash.events.ProgressEvent;
import flash.events.TimerEvent;
import flash.filesystem.File;
import flash.utils.Timer;

import mx.core.FlexGlobals;

public class PDF2SWFConverter
{
	private var command:String;
	private var finished:Boolean = false;
	private var error:Boolean = false;
	private var timer:Timer;
	
	public function PDF2SWFConverter(command:String)
	{
		this.command = command;	
	}
	
	public static function getInstance():PDF2SWFConverter{
		return new PDF2SWFConverter("/path/to/pdf2swf.exe");	
	} 
	
	public function convert(pdfPath:String, swfPath:String):Boolean {
		var nativeProcessStartupInfo:NativeProcessStartupInfo =  new NativeProcessStartupInfo();
		var commandFile:File = new File(command); 
		nativeProcessStartupInfo.executable = commandFile;
		var args:Vector. = new Vector.();
		args.push(pdfPath);
		args.push("-t");
		args.push("-T9");
		args.push("-o");
		args.push(swfPath);
		
		nativeProcessStartupInfo.arguments = args;
		var process:NativeProcess;

		timer = new Timer(1);

		process = new NativeProcess();
		process.start(nativeProcessStartupInfo);
		process.addEventListener(NativeProcessExitEvent.EXIT, onExit);
		process.addEventListener(ProgressEvent.STANDARD_ERROR_DATA, onErrorData);
		process.addEventListener(IOErrorEvent.STANDARD_ERROR_IO_ERROR, onIOError);
		
		timer.addEventListener(TimerEvent.TIMER, myTimerHandler);

		this.finished = false;
		this.error = false;
		timer.start();

		return !error;
	}
	
	protected function onExit(event:NativeProcessExitEvent):void
	{
		this.finished = true;
	}
	
	public function onErrorData(event:ProgressEvent):void
	{
      		this.error = true;
          		this.finished = true; 
      	}
	
	public function onIOError(event:IOErrorEvent):void
      	{
      		this.error = true;
      		this.finished = true;
      	}
      
      	public function myTimerHandler(e:TimerEvent):void{
      		if(this.finished)
		{
			timer.stop();
		} 
	}
}

Convertir PDF a SWF

Para llamar desde Flex al comando pdf2swf.exe, usamos los objectos: NativeProcessStartupInfo y NativeProcess.

NativeProcessStartupInfo, nos permite definir la información inicial de la llamada (nombre de comando y parametros) a un comando de linea. Este objecto es usado como parámetro para el método start del objeto NativeProcess.

NativeProcess, nos permite realizar la llamada a un comando de linea. Cabe advertir que por motivos de seguridad, no es posible ejecutar archivos .bat.

También es necesario señalar que para ejecutar de comandos de linea la aplicacion AIR tiene que tener configurado el perfil de escritorio extendido. Para esto tenemos que añadir lo siguiente al app.xml de la aplicacion AIR:

extendedDesktop

Como llamar a PDF2SWFConverter

Para llamar al objecto basta con lo siguiente:

var converter:PDF2SWFConverter = PDF2SWFConverter.getInstance();
converter.convert("/path/to/doc.pdf","/path/to/new/doc.swf");

Esta clase es un wrapper (envoltura) para el comando, la ventaja es que uno puede llamar a la clase, ejecutar la conversión y continuar con la secuencia de instrucciones gracias a que se usa el el objeto Timer.

UnitTests

Published / by Renan Huanca / 2 Comments on UnitTests

Hola Amigos, disculpen el tiempo que no pude postear. Lo que pasa es que en mi trabajo me tenían muy ocupado 🙂

Hoy no puedo escribir, pero por lo menos quiero compartir dos muy buenos podcasts de los amigos de JavaHispano.

Les recomiendo que escuchen ya que hablan de las estrategias que usaron algunas empresas para implementar un proceso de unittest.

JavaHispano Podcast – 064 – Test de aplicaciones (Parte 1)
* Blog de Alfredo Casado
* Blog de Julio César Pérez
* Blog de Jose Luis Bugarín
* ¿Por qué hacer test?
* Buenas prácticas para programar tests
* Principio FIRST (Ver capítulo 9)
* Dossier sobre el test de software
* Historia de integración: 1, 2, 3, 4
* Blog de Misko Hevery.
* Crear código testeable.
* Desarrollo TDD.

JavaHispano Podcast – 065 – Test de aplicaciones (Parte 2)
* Blog de Julio César Perez
* Blog de Alfredo Casado
* Blog de Jose Luis Bugarin
* Site de Junit: http://www.junit.org/
* Site de DbUnit: http://www.dbunit.org/
* Site de XMLUnit: http://xmlunit.sourceforge.net/
* Site de JMeter: http://jakarta.apache.org/jmeter/
* Site de Selenium: http://seleniumhq.org/
* Site de Watir: http://watir.com/
* Site de EasyMock: http://easymock.org/
* Site de Mockito: http://mockito.org/
* Site de Fitnesse: http://fitnesse.org/
* Site de Concordion:http://www.concordion.org/
* Site de Hudson: https://hudson.dev.java.net/
* Site de WebDriver: http://code.google.com/p/webdriver/
* Site de SoapUi: http://www.soapui.org/
* Plugin de chuck-norris para hudson.