analytics

miércoles, 23 de agosto de 2017

Spring Boot load war


Vamos a ver cómo cargar un .war ajeno a nuestro Tomcat Embebido utilizando Spring Boot.

Aquí ya veíamos como cargar Tomcat embebido con Spring Boot
Aquí vimos cómo utilizar el log de Spring Boot
Y aquí vimos cómo hacer que la conexión de Tomcat sea segura

A nuestro fichero de properties de Spring Boot le añadiremos las líneas del path y el context donde cargará el .war

war.context=/MyApp
war.path=MyApp.war

Y en nuestro código, tendremos que añadir lo siguiente

@Bean
    public EmbeddedServletContainerFactory servletContainerFactory() {
        return new TomcatEmbeddedServletContainerFactory() {

            @Override
            protected TomcatEmbeddedServletContainer getTomcatEmbeddedServletContainer(
                    Tomcat tomcat) {
                // Ensure that the webapps directory exists
                new File(tomcat.getServer().getCatalinaBase(), "webapps").mkdirs();

                try {

                    String warContext = properties.getProperty("war.context");
                    String warPath = properties.getProperty("war.path");
        
                    System.out.println("Will load " + warPath + " on " + warContext);

                    Context context = tomcat.addWebapp(warContext, new File(warPath).getAbsolutePath());
                    // Allow the webapp to load classes from your fat jar
                    context.setParentClassLoader(getClass().getClassLoader());
                } catch (ServletException ex) {
                    throw new IllegalStateException("Failed to add webapp", ex);
                }
                return super.getTomcatEmbeddedServletContainer(tomcat);
            }

        };
    }

Muy fácil no? y no hay que andar peleándose con la configuración de Tomcat. Spring Boot nos hace la gestión casi automáticamente...
Por cierto, asegúrate de tener la siguiente dependencia en tu POM de Maven

<dependency>
  <groupId>org.apache.tomcat.embed</groupId>
  <artifactId>tomcat-embed-jasper</artifactId>
  <version>8.5.5</version>
</dependency>

Spring Boot Key Alias



Para cargar un certificado de seguridad y poder tener un Tomcat embebido que de soporte a páginas a través de HTTPS, seguiremos los siguientes pasos.

Aquí veíamos como iniciar un Tomcat Embebido con un servicio desde Spring Boot
Y aquí veíamos cómo utilizar el logger de Spring Boot

En el fichero de application.properties de Spring Boot:


server.port=8012
server.ssl.key-store=server.pfx
server.ssl.key-store-password=mypass
server.ssl.keyStoreType=PKCS12
server.ssl.keyAlias=1


De donde:
- El port es obviamente el puerto en el que se desplegará el Tomcat y dará acceso a HTTPS
- El key-store es el certificado propiamente dicho. Existen varios formatos para el certificado, en este caso hemos usado el formato PKCS12, con un certificado de extensión .pfx. Aquí tienes un convertidor de formatos de certificado que puede ayudarte.
- El keyStoreType es el formato que hemos citado anteriormente
- El keyAlias es interesante profundizar más en él. Vamos a ello


El Key Alias:


Utilizando la herramienta keytool con el siguiente comando

keytool -list -keystore server.pfx

En nuestro caso, nos muestra algo similar a esto

1, 23-ago-2017, PrivateKeyEntry,
Huella Digital de Certificado (SHA1): 44:97:7B:EB:....... etc......

Obtendremos una lista de las entradas del certificado, donde cada línea es encabezada por los alias que incluye el certificado, de manera que si solo tenemos una entrada, por regla general, ésta será un "1", pero podríamos tener otras. Conviene localizar la entrada privada ya que será la que empleemos, y ésta es la que tendremos que poner en el fichero de properties.

Finalmente, si todo va bien, accediendo a

https://localhost:8012

debería funcionar la página. (Nótese que es HTTPS)



lunes, 21 de agosto de 2017

Java evitar mensajes por consola


Java, cómo evitar que nuestra aplicación muestre mensajes por pantalla al ejecutar:


¿Y por qué querríamos no ver los mensajes? Porque en una entrega a cliente es inconcebible que se vean mensajes del tipo "hola! llego a esta funcion!, bien !" o del tipo "NullPointerException". No es presentable y pondrá en seria duda nuestra profesionalidad.


Una opción sería no poner ningún System.out y evitar que las excepciones nos muestren el mensaje, lo cual no termina de ser buena idea, ya que no nos enteraremos de qué ocurre durante la ejecución de nuestra aplicación.

La mejor opción es externalizar todos los mensajes a un fichero de Log. Realmente, ésta sería la mejor opción. Tendremos todos los sucesos guardados, ordenados, con fecha y podremos acceder a ellos posteriormente. Aquí veíamos un ejemplo de uso con Log4J

Sin embargo, hay una opción intermedia, que es capturar los stream de out y err y redirigirlos hacia buffers que no apuntan a ningún sitio. Tal como a continuación se muestra.


    ByteArrayOutputStream baos1 = new ByteArrayOutputStream();
    PrintStream ps1 = new PrintStream(baos1);
     ByteArrayOutputStream baos2 = new ByteArrayOutputStream();
    PrintStream ps2 = new PrintStream(baos1);
    // IMPORTANT: Save the old System.out!
    PrintStream old = System.out;
    PrintStream old2 = System.err;
    // Tell Java to use your special stream
    
    System.out.println("Starting...");
    
    System.setOut(ps1);
    System.setErr(ps2);

    System.out.println("Siguiente...");


En el ejemplo anterior, veremos por consola el mensaje de "Starting", pero el mensaje "Siguiente" ya no lo veremos.

Tomcat embebido https


Vamos a configurar Tomcat desde Java (embebido) para utilizar un certificado de seguridad y poder acceder de manera segura a las aplicaciones que despliegue nuestro Tomcat. (vía HTTPS)

En nuestra función principal o Main:
.....
                Tomcat tomcat = new Tomcat();
                tomcat = new Tomcat();
                
                Service service = tomcat.getService();
                service.addConnector(getSslConnector());

                tomcat.getHost().setAutoDeploy(true);
                tomcat.getHost().setDeployOnStartup(true);
                tomcat.start();
             
                tomcat.getServer().await();
....

La función de configuración del service de Tomcat: (en función de la extensión de nuestro certificado, la keyStoreType tomará el valor de PEM, JKS o PKCS12)


private static Connector getSslConnector() {
    Connector connector = new Connector();
    connector.setPort(8090);
    connector.setSecure(true);
    connector.setScheme("https");
    connector.setAttribute("keyAlias", "tomcat");
    connector.setAttribute("keystorePass", "password");
//    connector.setAttribute("keystoreType", "JKS");
    connector.setAttribute("keystoreType", "PEM");
//    connector.setAttribute("keystoreType", "PKCS12");
    connector.setAttribute("keystoreFile", "private.pem");
    connector.setAttribute("clientAuth", "false");
    connector.setAttribute("protocol", "HTTP/1.1");
    connector.setAttribute("sslProtocol", "TLS");
    connector.setAttribute("maxThreads", "200");
    connector.setAttribute("protocol", "org.apache.coyote.http11.Http11AprProtocol");
    connector.setAttribute("SSLEnabled", true);
    return connector;

}

Una manera más moderna de hacer esto es con Spring Boot, donde además encontraremos más tutoriales y nos dará menos problemas. Aquí y Aquí tienes otros posts relativos a Spring Boot y Tomcat.