analytics

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

martes, 4 de julio de 2017

Java Tomcat embebido



Cómo embeber un Tomcat en código Java para ser ejecutado mediante un ejecutable .jar.
Además, cargaremos una web en dicho Tomcat, la cual tendremos previamente empaquetada en un fichero.war, para que sea accesible desde el navegador una vez ejecutada la aplicación. Utilizaremos Maven, Log4j y fichero de Properties, para hacer una aplicación lo más completa posible.

Objetivo: Tener un empaquetado .jar con TODO incluido, es decir, su propio Tomcat que despliega la aplicación .war, de manera que ejecutándolo, podemos acceder a la aplicación web en nuestro navegador. A mí no me suena mal, ya que permite mayor grado de limpieza en la máquina.


A continuación, parte del fichero "pom" de Maven


<properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <maven.compiler.source>1.8</maven.compiler.source>
        <maven.compiler.target>1.8</maven.compiler.target>
        <tomcat.version>8.5.5</tomcat.version>
    </properties>

    <dependencies>
  
        <dependency>
            <groupId>org.apache.tomcat</groupId>
            <artifactId>tomcat-catalina</artifactId>
            <version>${tomcat.version}</version>
        </dependency>
        <dependency>
            <groupId>org.apache.tomcat</groupId>
            <artifactId>tomcat-util</artifactId>
            <version>${tomcat.version}</version>
        </dependency>
        <dependency>
            <groupId>org.apache.tomcat.embed</groupId>
            <artifactId>tomcat-embed-core</artifactId>
            <version>${tomcat.version}</version>
        </dependency>
        <dependency>
            <groupId>org.apache.tomcat.embed</groupId>
            <artifactId>tomcat-embed-jasper</artifactId>
            <version>${tomcat.version}</version>
        </dependency>
  
         <dependency>
            <groupId>org.apache.tomcat.embed</groupId>
            <artifactId>tomcat-embed-websocket</artifactId>
            <version>${tomcat.version}</version>
        </dependency>
  
        <dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
            <version>1.2.17</version>
        </dependency>

    </dependencies>
  
  
    <build>
        <sourceDirectory>src</sourceDirectory>
        <plugins>
    
            <plugin>
                <groupId>org.apache.tomcat.maven</groupId>
                <artifactId>tomcat7-maven-plugin</artifactId>
                <version>2.2</version>
                <configuration>
                    <port>8080</port>
                    <path>/</path>
                </configuration>
            </plugin>
    
            <plugin>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.5.1</version>
                <configuration>
                    <source>1.8</source>
                    <target>1.8</target>
                </configuration>
            </plugin>
      
            
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-assembly-plugin</artifactId>
                <version>2.4.1</version>
                <configuration>
                    <!-- get all project dependencies -->
                    <descriptorRefs>
                        <descriptorRef>jar-with-dependencies</descriptorRef>
                    </descriptorRefs>
                    <!-- MainClass in mainfest make a executable jar -->
                    <archive>
                        <manifest>
                            <mainClass>directorio.hasta.el.Main *****</mainClass>
                        </manifest>
                    </archive>

                </configuration>
                <executions>
                    <execution>
                        <id>make-assembly</id>
                        <!-- bind to the packaging phase -->
                        <phase>package</phase>
                        <goals>
                            <goal>single</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
      


      
        </plugins>
    </build>



Y en el fichero de properties:

log.properties=log4j.properties
web.path=/My_App
web.war=C:\\.........\\My_App.war
web.port=8080
web.workingdir=/




El fichero log4j.properties, con la configuración de log4j para que nos escriba un fichero de log y además, nos escriba por consola:


# Root logger option
log4j.rootLogger=DEBUG, file, stdout

# Direct log messages to a log file
log4j.appender.file=org.apache.log4j.RollingFileAppender
log4j.appender.file.File=C:\\LOGS\\mylog.log
log4j.appender.file.MaxFileSize=10MB
log4j.appender.file.MaxBackupIndex=10
log4j.appender.file.layout=org.apache.log4j.PatternLayout
log4j.appender.file.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %-5p %c{1}:%L - %m%n

# Direct log messages to stdout
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target=System.out
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %-5p %c{1}:%L - %m%n



Por último, nuestro Main:


 public static void main(String[] args) {

        Properties properties = getProperties();
        if (properties != null) {
            try {

                // carga fichero de configuracion de log
                PropertyConfigurator.configure(new FileInputStream(properties.getProperty("log.properties")));
                Logger logger = LogManager.getLogger(Main.class);                

                String mWorkingDir = properties.getProperty("web.workingdir");

                Tomcat tomcat = new Tomcat();
                tomcat = new Tomcat();
                int port = Integer.parseInt(properties.getProperty("web.port"));
                tomcat.setPort(port);
                tomcat.setBaseDir(mWorkingDir);
                tomcat.getHost().setAppBase(mWorkingDir);
                tomcat.getHost().setAutoDeploy(true);
                tomcat.getHost().setDeployOnStartup(true);

                try {
                    tomcat.start();
                } catch (LifecycleException e) {                   
                    logger.error("Tomcat could not be started: LifecycleException in Main class");
                    e.printStackTrace();
                }
                logger.debug("Tomcat started on " + tomcat.getHost());

                // Alternatively, you can specify a WAR file as last parameter in the following call e.g. "C:\\Users\\admin\\Desktop\\app.war"
                Context appContext = tomcat.addWebapp(tomcat.getHost(), properties.getProperty("web.path"), properties.getProperty("web.war"));
                logger.debug("Deployed " + appContext.getBaseName() + " as " + appContext.getBaseName());

               
                tomcat.getServer().await();
            } catch (Exception e) {
                System.out.println("Unable to start Tomcat_Embedded_War_Loader.");
                e.printStackTrace();
            }
        }

    }

public static Properties getProperties() {
        Properties prop = new Properties();
        InputStream input = null;

        try {

            input = new FileInputStream("config.properties");
            
            // load a properties file
            prop.load(input);
            

            return prop;
        } catch (IOException ex) {
            ex.printStackTrace();
            return null;
        } finally {
            if (input != null) {
                try {
                    input.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }

    }


miércoles, 12 de abril de 2017

Validar JTextField cambiando su color



Vamos a ver como hacer unos métodos estáticos muy simples que nos permitirán validar campos de Java  Swing tipo JTextField. Nos devolverán un booleano indicando si valida, y además, cambiarán el color de fondo del JTextField.

No hay mucho más que comentar, a continuación el código


    public static final Color COLOR_RIGHT = Color.WHITE;
    public static final Color COLOR_ERROR = new Color(255,153,153);
    
    
    public static boolean validateTextField(JTextField textField){
        if (textField.getText()!=null && !"".equalsIgnoreCase(textField.getText())) {
            textField.setBackground(COLOR_RIGHT);
            return true;
        }
        textField.setBackground(COLOR_ERROR);
        return false;
    }
    
    
    public static boolean validateEmailTextField(JTextField textField){
        if (textField.getText()!=null && !"".equalsIgnoreCase(textField.getText())) {
            
            String text = textField.getText();
            if (text.contains("@") && text.contains(".")){
                textField.setBackground(COLOR_RIGHT);
                return true;
            } else {
                textField.setBackground(COLOR_ERROR);
                return false;
            }
        }
        textField.setBackground(COLOR_ERROR);
        return false;
    }
    
    
    public static boolean validateDoubleField(JTextField textField){
        if (textField.getText()==null || "".equalsIgnoreCase(textField.getText())) {
            textField.setBackground(COLOR_ERROR);
            return false;
        }
        
        try {
            Double d = Double.parseDouble(textField.getText());
            textField.setBackground(COLOR_RIGHT);
            return true;
        } catch (Exception e){            
            textField.setBackground(COLOR_ERROR);
            return false;
        }
    }

miércoles, 15 de marzo de 2017

Grabar desde Java usando VLC

Cómo grabar desde Java utilizando la aplicación VLC y la librería "vlcj"




Partiremos de que vamos a utilizar Maven, la librería vlcj y la aplicación VLC (debe estar instalada en nuestro equipo). Lo que vamos a hacer es grabar la entrada de micrófono manejando VLC desde nuestro código Java. Cuidado con las versiones de vlcj (v2.4.1), jna y jna-platform (v3.5.2). Existen versiones posteriores de las mismas, pero pueden ser incompatibles entre sí. Con las que he puesto funciona, hay otras que dan problemas.

En nuestro pom.xml de Maven:

...

<properties>
        <jna.version>3.5.2</jna.version>
        <slf4j.version>1.7.10</slf4j.version>
</properties>

...

       <dependency>
            <groupId>uk.co.caprica</groupId>
            <artifactId>vlcj</artifactId>
            <version>2.4.1</version>
        </dependency>
        <dependency>
            <groupId>net.java.dev.jna</groupId>
            <artifactId>jna</artifactId>
            <version>${jna.version}</version>
        </dependency>
        <dependency>
            <groupId>net.java.dev.jna</groupId>
            <artifactId>jna-platform</artifactId>
            <version>${jna.version}</version>
        </dependency>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-api</artifactId>
            <version>${slf4j.version}</version>
        </dependency>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-log4j12</artifactId>
            <version>${slf4j.version}</version>
            <scope>test</scope>
        </dependency>

...


Ahora veamos el código para iniciar la grabación


    NativeLibrary.addSearchPath(RuntimeUtil.getLibVlcLibraryName(), "C:/Program Files/VideoLAN/VLC");         
            Native.loadLibrary(RuntimeUtil.getLibVlcLibraryName(), LibVlc.class);
        
            EmbeddedMediaPlayerComponent mediaPlayerComponent = new          EmbeddedMediaPlayerComponent();

            JFrame frame = new JFrame("Gemma Recorder: Don't close");
            frame.setContentPane(mediaPlayerComponent);
            frame.setLocation(100, 100);
            frame.setSize(1050, 600);
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            frame.setVisible(true);

            //Save video
            File dir = new File("URL DE CARPETA DESTINO DE GRABACIONES");
            DateFormat df = new SimpleDateFormat("yyyyMMdd-HHmmss");
            String fileName = dir.getAbsolutePath() + "/Capture-" + df.format(new Date()) + ".mp3";
            System.out.println("Grabando en " + fileName);
            String mediaURL = "dshow://";
            mediaPlayerComponent.getMediaPlayer().playMedia(mediaURL, ":sout=#transcode{vcodec=none,venc=x264{cfr=16},scale=1,acodec=mp3,ab=160,channels=2,samplerate=44100}:file{dst=" + fileName + "}");



Cuando queramos detener la grabación, simplemente, 

mediaPlayerComponent.getMediaPlayer().stop();

A continuación, enlaces a la documentación oficial de comandos VLC

https://wiki.videolan.org/VLC_command-line_help/
https://wiki.videolan.org/Documentation:Command_line/
https://wiki.videolan.org/Command_line/








lunes, 2 de enero de 2017

Servidor de sockets TCP-IP


Servidor de Sockets TCP-IP



Ahora vamos a ver como crear un servidor de sockets por tcp-ip, es decir, una pequeña aplicación que estará permanentemente "escuchando" en un puerto a la espera de conexiones entrantes por dicho puerto. Cuando llegue una petición, crearemos un hilo con un nuevo cliente que ejecutará el tratamiento correspondiente a la nueva petición.

Para empezar, vamos a ver como quedaría la clase de ServerSockets



import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import org.apache.log4j.Logger;

public class SocketServer implements Runnable {
    
    private ServerSocket serverSocket;
    private boolean socketReadActive;
    private int timeOut;
    final static Logger mainLog = Logger.getLogger(SocketServer.class);

    public  SocketServer(int port, int timeOut) {
        try{
            this.socketReadActive = true;
            this.serverSocket = new ServerSocket(port);
            this.timeOut = timeOut;
        } catch (IOException ex) {
            mainLog.error("SocketServer (): IOException" ,ex);
            this.closeSocketServer();
        }
    }

    public void run() {
         
     
        while (this.socketReadActive) {
            try {
                    Socket clientSocket = this.serverSocket.accept();
                    Client client = new Client(clientSocket, this.timeOut);
                    new Thread(client).start();                    
                    mainLog.debug("Connected client: " + clientSocket.getInetAddress() + ":" + clientSocket.getPort());
            } catch (Exception ex) {
                mainLog.error("run (): Exception" ,ex);
                this.closeSocketServer();
            }
        }
    }

    public void closeSocketServer() {
        this.socketReadActive = false;
        try {
            if (this.serverSocket != null) {
                this.serverSocket.close();
                this.serverSocket = null;
            }
        }
        catch(Exception ex){
            mainLog.error("closeSocketServer (): Exception" ,ex);
        }
    }
}



Como veis, es sencillo. Un Thread que se ejecuta constantemente a la escucha de nuevas conexiones entrantes. Cuando llega una conexión entrante, instancia un cliente Client, cuyo código será



import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.Socket;
import java.net.SocketException;
import java.util.ArrayList;
import java.util.Iterator;
import org.apache.log4j.Logger;


public class Client implements Runnable{

 final static Logger mainLog = Logger.getLogger(Client.class);
 
 private Socket clientSocket;
 private int timeout;
 
 public Client(Socket clientSocket, int timeout){
  this.clientSocket = clientSocket;
  this.timeout = timeout;
  
 }
 
 
 @Override
 public void run() {
  
  // set timestamp al socket de cliente
  try {
   this.clientSocket.setSoTimeout(timeout);
  } catch (SocketException e) {
   mainLog.error("Client run error " , e);
  }
  
  // procesar la petición
   BufferedReader input;
  try {
   
   input = new BufferedReader(new InputStreamReader(this.clientSocket.getInputStream()));
   String trama = input.readLine();
   
   
   try{
    
    // AQUI vendría el código de tratamiento de la petición

   } catch (Exception e){    
    mainLog.error("Client run error conectando a BD " , e);
   }
   
   
  } catch (Exception e) {      
   mainLog.error("Client run error abriendo socket ",e);
  }
          

 }


}

Sencillo cliente que se ejecuta en un hilo aparte (cada nuevo cliente será un hilo distinto), lo cual permite múltiples ejecuciones de cliente paralelas. El código de tratamiento de la petición ya depende del caso concreto.

jueves, 29 de diciembre de 2016

Java Log con Log4j

Utilizar Log4j es muy fácil



Log4j es una librería Java que nos facilita mucho el uso de ficheros de Log. Un fichero de log nos permite depurar y mantener la aplicación. Simplemente es un fichero donde se irán añadiendo cadenas de texto conforme nuestro programa se ejecute. De esta manera, cuando no tengamos otro sistema de debug disponible (por ejemplo, en tiempo de ejecución), podremos saber qué ocurre con nuestra aplicación.



Código


import org.apache.log4j.LogManager;
import org.apache.log4j.Logger;
import org.apache.log4j.PropertyConfigurator;


public class TestLogger{

   public static void main(String[] args) {  
        try {           

            // carga fichero de configuracion de log
            PropertyConfigurator.configure(TestLogger.class.getResourceAsStream("log4j.properties")); 
            Logger logger = LogManager.getLogger(TestLogger.class);
            logger.error("error de prueba");     
            
        } catch (IOException ex) {            
         ex.printStackTrace();
        }
  
   }
}
 

Donde "log4j.properties" es el fichero de configuración del Logger. (no es obligatorio, pero si no lo añadimos, nos utilizará la configuración por defecto, la cual es mostrar los mensajes de log por consola). 
La sentencia "logger.error("error de prueba")", es un ejemplo de inserción de mensajes de log.

** Nota: en este ejemplo, estoy utilizando la versión de la librería log4j-1.2.17.jar, la cual, simplemente, añadiremos a nuestro proyecto.


Fichero de configuración de log4j


El contenido de "log4j.properties" es el siguiente

# Root logger option
log4j.rootLogger=DEBUG, file, stdout

# Direct log messages to a log file
log4j.appender.file=org.apache.log4j.RollingFileAppender
log4j.appender.file.File=C:\\LOGS\\outLog.txt
log4j.appender.file.MaxFileSize=10MB
log4j.appender.file.MaxBackupIndex=10
log4j.appender.file.layout=org.apache.log4j.PatternLayout
log4j.appender.file.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %-5p %c{1}:%L - %m%n

# Direct log messages to stdout
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target=System.out
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %-5p %c{1}:%L - %m%n


Donde le indicamos que el nivel más bajo de LOG que queremos mostrar es el nivel DEBUG. Esto significa que todo lo que ocurra en el programa cuya importancia sea mayor o igual al nivel DEBUG, se añadirá al log, y lo que tenga menor importancia no se añadirá.


Estos son los niveles de prioridad: (cuanto más alto, mayor prioridad o gravedad)
  • OFF
  • FATAL
  • ERROR
  • WARN
  • INFO
  • DEBUG
  • TRACE
  • ALL

También le especificamos que el log nos lo muestre tanto por consola (stdout) como en un fichero de log (file).

Por último, detallamos algunas opciones como la ruta del fichero de log de output y el tamaño máximo del fichero de log, para que no crezca indefinidamente.


log4j.appender.file.File=C:\\LOGS\\outLog.txt
log4j.appender.file.MaxFileSize=10MB

En resumen, una manera muy simple de tener un log en nuestras aplicaciones y saber qué ocurre en tiempo de ejecución.

Fichero configuración Java properties


Fichero configuración Java properties



A veces nos hemos encontrado con la necesidad de crear un fichero de propiedades que permita modificar las mismas una vez desplegada la aplicación. Imaginemos que creamos una aplicación que se conecta a un servidor para realizar una operación y por motivos de seguridad, ese servidor cambia de vez en cuando los datos de acceso (algo común). El fichero properties permitirá modificar parámetros de configuración sin necesidad de volver a tocar el código, recompilar, volver a colocar el ejecutable en su sitio, etc...



Las ventajas de su uso son precisamente:

  1. - Permite modificar parámetros sin tener que volver a tocar el código ni recompilar
  2. - Permite utilizar una misma aplicación para entornos distintos con distintas configuraciones
  3. - Permite a usuarios no experimentados con la programación, poder modificar los parámetros a través de un fichero legible. "user-friendly"
Así pues, por ejemplo, podemos utilizarlo de la siguiente manera



import java.util.Properties;

public class TestConfig{

    public static void main(String[] args) {
        Properties properties = new Properties();
        try {
            properties.load(TestConfig.class.getResourceAsStream("config.properties"));
            System.out.println(properties.getProperty("log.properties"));
        } catch (IOException ex) {            
         ex.printStackTrace();
        }

    }
}

Donde nuestro fichero de propiedades se llamará "config.properties"

properties.load(TestConfig.class.getResourceAsStream("config.properties"));


Y una de sus propiedades puede ser "log.properties". Lo que hacemos aquí es simplemente leer la propiedad del fichero de propiedades cuya etiqueta es "log.properties"

System.out.println(properties.getProperty("log.properties"));


Donde nuestro fichero de properties se construye mediante el patrón 
etiqueta=valor 
* Nota: Las etiquetas pueden organizarse en subetiquetas mediante un punto "."
El valor no debe sobrepasar una línea

Por ejemplo, nuestro fichero de properties, "config.properties"podría ser este


database.ip=192.168.0.99
database.port=2456
database.schema=Schema
database.user=db_user
socket.timeOut=60000
server.listenport=3500
log.properties=log4j.properties


En definitiva, un mecanismo muy simple para tener un fichero de propiedades que permita a nuestra aplicación ser mucho más genérica y facilitar su mantenimiento.