analytics

jueves, 6 de julio de 2017

Spring Boot utilizar su logger

Vamos a ver cómo podemos utilizar el logger de Spring Boot para poder sacar nuestros mensajes de debug sin reinventar la rueda y utilizando el sistema de log de Spring Boot.
La llamada en sí misma al logger no tiene mucho de especial, se hace de la manera habitual, pero hay que hacer un par de ajustes en configuración.


import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class SBLogger{
    private final Logger logger = LoggerFactory.getLogger(this.getClass());

    public static void main(String[] args) throws Exception {

                // arrancar Spring Boot
                SpringApplication.run(this.getClass(), args);

                logger.debug("Sample debug message");              
logger.info("Sample info message");
logger.warn("Sample warn message");
logger.error("Sample error message");

   }
}



En nuestro fichero pom.xml, entre otras cosas, habrá que añadir lo siguiente

        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-api</artifactId>
            <version>1.7.19</version>
        </dependency>
        <dependency>
            <groupId>org.apache.logging.log4j</groupId>
            <artifactId>log4j-slf4j-impl</artifactId>
            <version>2.5</version>
        </dependency>
        <dependency>
            <groupId>org.apache.logging.log4j</groupId>
            <artifactId>log4j-api</artifactId>
            <version>2.5</version>
        </dependency>
        <dependency>
            <groupId>org.apache.logging.log4j</groupId>
            <artifactId>log4j-core</artifactId>
            <version>2.5</version>
        </dependency>
        <dependency>
            <groupId>org.apache.logging.log4j</groupId>
            <artifactId>log4j-jcl</artifactId>
            <version>2.5</version>
        </dependency>



Como siempre, si no utilizamos Maven, habrá que importar las librerías a mano, entre ellas Spring Boot y las de logging que aparecen en el pom.xml anterior.
Por otro lado, habrá que tocar un poco la configuración de Spring Boot, por lo tanto, en el archivo application.properties, habrá que incluir las siguientes claves.


logging.file=my_file.log
logging.level.org.springframework.web=INFO
logging.level.guru.springframework.blogs.controllers=INFO
logging.level.org.hibernate=ERROR
log4j.logger.org.thymeleaf=DEBUG



Por cierto, si no tienes un fichero de application.properties, deberás crearlo a mano. Spring Boot lo buscará y si lo encuentra, le hará caso a la hora de arrancar. Deberás ubicarlo en /src/main/resources

Java toString en cascada para debug



Vamos a ver cómo podemos hacer el método toString a lo largo de nuestras clases de manera que nos resulte muy cómodo para debugear, sin tener que esforzarse demasiado y manteniendo el orden, cada clase contendrá su output en String adecuado y sólo el suyo. Al final, tendremos un toString() en cascada que cumplirá con dos objetivos

  1. Facilitará el debug y nos resultará muy cómodo
  2. Nos mantendrá el orden y limpieza de código

Veamos cómo conseguirlo, es muy sencillo.

Tendremos dos clases: Call y Connection. La relación entre ellas es que una Call tiene una lista de Connections.



Veamos primero la clase Connection.



public class Connection {
    
    private String phone;
    private int direction = 0;
    private String substate;

     // ... aquí irían los métodos get/set


    @Override
    public String toString() {
        return "Connection{" + "phone=" + phone + ", direction=" + direction + ", substate=" + substate + '}';
    }

    
}



Hasta aquí nada especial, simplemente, vamos a darnos cuenta de que es esencial que el toString esté representado en su lugar, es decir, la representación String de una Connection, deberá estar dentro de la clase Connection. (por motivos de orden y limpieza). Veamos la clase Call.


public class Call {
    
    private String callID="";
    private int state = 0;
    private int type = 0;
    private ArrayList<Connection> connections = new ArrayList<Connection>();
    
    
    // ... aquí irían los métodos get/set

    @Override
    public String toString() {
        String retVal = "Call{" + "callID=" + callID + ", state=" + state + ", type=" + type+"\n" ;
        for (Iterator<Connection> iterator = connections.iterator(); iterator.hasNext();) {
            Connection next = iterator.next();
            retVal+=next.toString()+"\n";
        }
        retVal+="}";
        return retVal;
    }

    
}


Si prestamos atención al método toString, ya vemos en qué va a consistir la estructura en cascada. Simplemente llamando al método toString de una Call, ya nos imprimirá toda la lista de Connections, dado que la clase Connection también implementará su propio toString, como hemos visto anteriormente.

Es muy sencillo, pero muy potente. Para objetos compuestos con varios niveles de profundidad, debugear puede terminar siendo un infierno. Con éste método, cada clase se genera su propio String de debug y al final, simplemente, llamando al toString de la clase cabeza, tendremos el debug completo de todos sus "hijos". Con poco esfuerzo y sin sacrificar la limpieza.



miércoles, 5 de julio de 2017

Java Swing cargar y ver imagen jpg en jPanel



Vamos a ver cómo abrir una imagen, copiarla en un fichero auxiliar y visualizarla en un jPanel. Esto se emplea cuando queremos por ejemplo ver un logotipo cargado desde un fichero.


  1. Primero, utilizaremos jFileChooser para hacer la selección del fichero. 
  2. Después, haremos una copia de la imagen para guardarla en un directorio de nuestro interés. (este paso es opcional)
  3. Por último, visualizaremos la imagen en un jPanel.



Esta es la función que abrirá un diálogo para seleccionar el fichero de imagen a cargar.


      final JFileChooser fc = new JFileChooser();
            int returnVal = fc.showOpenDialog(null);

            if (returnVal == JFileChooser.APPROVE_OPTION) {
                File file = fc.getSelectedFile();
                try {

                    String nombreImg = file.getName();
                    if (nombreImg.endsWith(".jpg")
                            || nombreImg.endsWith(".png")
                            || nombreImg.endsWith(".bmp")
                            || nombreImg.endsWith(".jpeg")) {

                        

                        File dest = new File(System.getProperty("user.dir") + "/" + nombreImg);
                        copyFileUsingStream(file, dest);
                        this.imagen= (dest.getName());
                        loadImage(dest.getName());

                    }

                } catch (Exception ex) {
                    ex.printStackTrace();
                    JOptionPane.showMessageDialog(null, "Error abriendo fichero");
                }

            }



A continuación, la función de copia de imagen de un origen a un destino. Este paso es solamente opcional. En el ejemplo original, me interesó guardar las imágenes que el usuario seleccionaba en un directorio.


private static void copyFileUsingStream(File source, File dest) throws IOException {
        InputStream is = null;
        OutputStream os = null;
        try {
            is = new FileInputStream(source);
            os = new FileOutputStream(dest);
            byte[] buffer = new byte[1024];
            int length;
            while ((length = is.read(buffer)) > 0) {
                os.write(buffer, 0, length);
            }
        } finally {
            is.close();
            os.close();
        }
    }




Por último, veremos cómo cargar la imagen en un jPanel y poderla visualizar en el panel.


private void loadImage(String name) {

        try {
            String string = System.getProperty("user.dir") + "/" + name;

            ImageIcon ii = new ImageIcon((string));

            ImagePanel panel = new ImagePanel(ii.getImage()); // NOI18N
            jPanel2.add(panel, BorderLayout.CENTER);
            panel.setCustomWidth(jPanel2.getWidth());
            panel.setCustomHeight(jPanel2.getHeight());
            panel.validate();
            panel.repaint();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }




** Cabe destacar que el jPanel donde se visualizará la imagen, está con un Layout tipo BORDERLAYOUT. Por este motivo, al añadir la imagen, se tiene el parámetro BorderLayout.CENTER.


Java cómo poblar de objetos un JList



Vamos a ver un ejemplo muy simple de cómo poblar un JLIST.
Para empezar, introduciremos un jScrollPanel en la ventana y le añadiremos dentro un componente jList. Entonces, en el constructor de la ventana, llamaremos a nuestra función de poblar el jList (loadPersonas) para añadirle los elementos.


private void loadPersonas() {
        
        ArrayList<Persona> lista = new ArrayList<Persona>();
        // .... aquí añadiriamos las personas al array
        // o bien lo recuperaríamos de un fichero o una base de datos
        
        
        jList1.setModel(new AbstractListModel() {

            @Override
            public int getSize() {
                return lista.size();
            }

            @Override
            public Object getElementAt(int index) {
                return lista.get(index);
            }
        });
        
    }




Hay que tener en cuenta un detalle. En la clase Persona, deberemos sobrescribir el método toString, para que en el jList, nos aparezca lo que deseamos (en este caso, el nombre de la persona). En caso de no hacerlo, nos aparecerá el toString que la API de Java implementa por defecto heredado.



Persona.java

....

public String toString(){
     return this.nombre;
}

....


Podemos configurar la propiedad del jList de SELECTION_MODE para que tome el valor de SINGLE, de esta manera, nos aseguramos que solo se podrá seleccionar una persona de la lista.
En el momento que queramos obtener la Persona seleccionada en el jList, podremos simplemente, castear de la siguiente manera:


Persona p = (Persona)jList1.getSelectedValue();



Es fácil tratar con jList e introducirles objetos de clases propias mediante el mecanismo de sobrescribir el método toString().

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();
                }
            }
        }

    }


Java escribir y leer fichero Serializable



Vamos a ver cómo podemos de una manera ultra simple, guardar y leer información en ficheros desde Java utilizando la Serialización. No hace falta ningún tipo de conversión ni parsear campo a campo. La API de Java tiene mecanismos que nos hacen todo el trabajo y sólo necesitaremos crear la infraestructura para poder leer y escribir en fichero. Incluso, podremos escribir y leer directamente un ArrayList de nuetro objeto creado. Suena fácil y simple, no? Vamos a verlo.



Para empezar, tenemos la clase Persona que implementa Serializable.

public class Persona implements Serializable {

    private String nombre;
    private String apellido;
    private int edad;

    public String getNombre() {
        return nombre;
    }

    public void setNombre(String nombre) {
        this.nombre = nombre;
    }

    public String getApellido() {
        return apellido;
    }

    public void setApellido(String apellido) {
        this.apellido = apellido;
    }

    public int getEdad() {
        return edad;
    }

    public void setEdad(int edad) {
        this.edad = edad;
    }

    public Persona() {

    }

}






Por otro lado, vamos a crearnos una clase aparte para tratar con los ficheros. Ésta clase contendrá el método de leer y el método de escribir. El funcionamiento es muy sencillo. Trataremos siempre con un ArrayList de Personas. Se lo pasaremos como parámetro a la función de escribir en fichero. Por otro lado, la función de leer de fichero nos devolverá un ArrayList de Personas con las personas introducidas en el fichero. Y nos olvidamos de cómo se lee y escribe el fichero o de qué formato tenga. Así de fácil.


public class FicherosIO {

    public static final String FILE_NAME = "usuarios.dat";

    public void escribirFichero(ArrayList<Persona> usuarios) {
        ObjectOutputStream out = null;

        try {
            out = new ObjectOutputStream(new FileOutputStream(FILE_NAME));
            out.writeObject(usuarios);
            out.close();
        } catch (IOException ex) {
            System.out.println(ex.getMessage());
        } finally {
            if (out != null) {
                try {
                    out.close();
                } catch (IOException ex) {
                    System.out.println(ex.getMessage());
                }
            }
        }

    }

    public ArrayList<Persona> leerFichero() {

        // comprobar si el fichero existe, si no existe, lo creamos
        File f = new File(FILE_NAME);
        if (!f.exists()) {
            try {
                f.createNewFile();
            } catch (IOException ex) {
                Logger.getLogger(Fichero.class.getName()).log(Level.SEVERE, null, ex);
            }
        }

        ObjectInputStream in = null;
        ArrayList<Persona> lista;

        try {
            //primero se leen los datos que se almacenaron en el fichero; los datos de entrada
            in = new ObjectInputStream(new FileInputStream(FILE_NAME));
            lista = (ArrayList<Persona>) (in.readObject());
            return lista;
        } catch (Exception e) {
            System.out.println(e.getMessage());
            return new ArrayList<Persona>();
        } finally {
            //hay que asegurarse de cerrar el fichero para que los dados realmente se guarden
            if (in != null) {
                try {
                    in.close();
                } catch (IOException ex) {
                    System.out.println(ex.getMessage());
                }
            }
        }

    }
}




Por último, recordad que existe un "peligro" y es que si tenemos un fichero ya creado y modificamos la clase guardada, es decir, la clase Persona, Java se armará un lio con la versión de las clases y no será capaz de leer la lista de Personas del fichero, ya que no reconocerá su definición de la clase Persona, como la que se encuentra en el fichero. Por lo tanto, este sistema tiene esta debilidad. Las clases deben permanecer inmodificables una vez los ficheros han sido escritos con una versión.

lunes, 3 de julio de 2017

Spring Boot iniciar Tomcat y un servicio





Vamos a ver cómo utilizar Spring Boot para embeber (incluir insertado) un Tomcat que despliegue un servicio sin tener que instalar y configurar Tomcat en el equipo. Al final el ejecutable será un .jar el cual ejecutaremos mediante "java -jar". Y sin necesidad de tener previamente un Tomcat instalado en el equipo, podremos disponer de él para desplegar nuestro servicio.

Utilizaremos Maven y el sistema de log de Spring Boot para incluir nuestros mensajes de log. Por otro lado, incluiremos un fichero de properties de configuración de Spring Boot al cual también podemos añadir nuestras propias claves de configuración.


Nuestro fichero "pom" de Maven

   <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.5.4.RELEASE</version>
    </parent>
    
    <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>
        <!-- Spring boot main class -->
        <start-class>nombre.de.paquetes.hasta.el.Main****</start-class>
    </properties>
    
    
    <dependencies>
        
        <dependency>          
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>              
        </dependency>
        
        
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-api</artifactId>
            <version>1.7.19</version>
        </dependency>
        <dependency>
            <groupId>org.apache.logging.log4j</groupId>
            <artifactId>log4j-slf4j-impl</artifactId>
            <version>2.5</version>
        </dependency>
        <dependency>
            <groupId>org.apache.logging.log4j</groupId>
            <artifactId>log4j-api</artifactId>
            <version>2.5</version>
        </dependency>
        <dependency>
            <groupId>org.apache.logging.log4j</groupId>
            <artifactId>log4j-core</artifactId>
            <version>2.5</version>
        </dependency>
        <dependency>
            <groupId>org.apache.logging.log4j</groupId>
            <artifactId>log4j-jcl</artifactId>
            <version>2.5</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-security</artifactId>
            <exclusions>
                <exclusion>
                    <groupId>ch.qos.logback</groupId>
                    <artifactId>logback-classic</artifactId>
                </exclusion>
            </exclusions>
        </dependency>

    </dependencies>
    
    
    <build>
        <resources>
            <resource>
                <directory>src/main/resources</directory>
                <targetPath>${project.build.directory}</targetPath>
                <includes>
                    <include>log4j.properties</include>
                    <include>application.properties</include>
                </includes>
            </resource>
        </resources>
        <plugins>
            
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>                
            </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>nombre.de.paquetes.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>






A continuación, nuestro fichero "application.properties", el cual se situará en /src/main/resources

# puerto donde se despliega este servicio
server.port=8012
logging.file=ecall.log
security.basic.enabled=false
logging.level.org.springframework.web=INFO
logging.level.guru.springframework.blogs.controllers=INFO
logging.level.org.hibernate=ERROR
log4j.logger.org.thymeleaf=DEBUG





A continuación, la clase Main, donde definiremos el servicio a llamar para ser registrado en Spring Boot y que éste lo reconozca al iniciarse.


@Controller
@EnableAutoConfiguration
public class MainClass {


    @RequestMapping("/")
    @ResponseBody
    String home() {
        // este método define lo que aparecerá cuando en el navegador accedamos a la dirección localhost:puerto/
        return "Hello World! Spring Boot working !!";
    }


    /*
        A continuación es la manera de registrar un servlet en Spring Boot, en este caso en /recepcion
    */    
    @Bean
    public ServletRegistrationBean registro() {
        return new ServletRegistrationBean(new NombreDeNuestroServlet(), "/recepcion");
    }


     public static void main(String[] args) throws Exception {
        
        // load properties
         Properties properties = getProperties();
        try {
            

                SpringApplication.run(MainClass.class, args);

            } catch (Exception e) {
                System.out.println("Unable to start SPRING BOOT ");                
                e.printStackTrace();
            }
        
    }

}




Por último, nuestro Servlet, que es absolutamente común, pero por probar algo en su llamada, haremos una llamada al logger para introducir algún mensaje y comprobar que al acceder a localhost:puerto/recepcion , realmente accede a este servlet y ejecuta su código.



public class NombreDeNuestroServlet extends HttpServlet {

    private final Logger logger = LoggerFactory.getLogger(this.getClass());
    
    public void doPost(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException {

        logger.debug("Sample debug message");                
logger.info("Sample info message");
logger.warn("Sample warn message");
logger.error("Sample error message");

        
       
        // Obtenemos un objeto Print Writer para enviar respuesta
        res.setContentType("text/html");
        PrintWriter pw = res.getWriter();
        pw.println("200 OK");
        pw.close();
    }

    public void doGet(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException {
        doPost(req, res);

    }
    


}





Finalmente, al hacer un clean and build, nuestro IDE nos creará un .jar, el cual simplemente ejecutando con java -jar, nos desplegará el Tomcat y nuestro servicio, quedando ya listo para su acceso. Al final, queda un código muy simple y elegante que nos permite tener la máquina servidor más limpia ya que no es necesario instalar Tomcat. Cada aplicación es muy bien "educada" y se trae su propio Tomcat, su propia configuración, se autodespliega y cuando finaliza su ejecución, no quedan rastros...

Una maravilla, no?