Buscar este blog

sábado, 31 de agosto de 2013

Weblogic despliega dos veces / Weblogic deploy twice

Al trabajar con weblogic y eclipse, muchas veces da la impresión de que las aplicaciones se despliegan dos veces. Una junto al arranque del servidor y, una vez éste está running, vuelve a hacer el deploy correspondiente.

Parece que el problema está en la carpeta tmp del server que no se borra durante los reinicios.

Para solucionarlo se puede modificar el script de arranque de startWebLogic.cmd añadiendo la instrucción  rd de MS-DOS para borrar el tmp antes de iniciar:


 @ECHO OFF  
 @REM WARNING: This file is created by the Configuration Wizard.  
 @REM Any changes to this script may be lost when adding extensions to this configuration.  
 SETLOCAL  
 set DOMAIN_HOME=C:\Oracle\Middleware\user_projects\domains\comercio_domain  

 @REM Borrar tmp  
 rd /S /Q %DOMAIN_HOME%\servers\AdminServer\tmp  

 call "%DOMAIN_HOME%\bin\startWebLogic.cmd" %*  
 ENDLOCAL  


Este archivo está en el DOMAIN_HOME de Weblogic.

domingo, 11 de agosto de 2013

Error: com.sun.xml.ws.wsdl.parser.InaccessibleWSDLException, message: 2 counts of InaccessibleWSDLException.

Trabajando con Weblogic 10.3.5, JAX-WS y Axis2 puede que aparezca el siguiente error:


 weblogic.wsee.jaxws.framework.policy.advertisementimpl.AdvertisementHelperImpl registerExtension  
 ADVERTENCIA: Registering oracle.j2ee.ws.wsdl.extensions.addressing.AddressingExtensionRegistry extension failed; java.lang.ClassNotFoundException: oracle.j2ee.ws.wsdl.extensions.addressing.AddressingExtensionRegistry  
 weblogic.wsee.jaxws.spi.WLSServiceDelegate addWsdlDefinitionFeature  
 GRAVE: Failed to create WsdlDefinitionFeature for wsdl location: https://xxxxxx.xx/xxxxx?wsdl, error: com.sun.xml.ws.wsdl.parser.InaccessibleWSDLException, message: 2 counts of InaccessibleWSDLException.  

Realmente no es un problema, ya que todo funciona correctamente, pero va estar llenando los logs de basura innecesaria.
El origen está en la incompatibilidad de jars del tipo javax. que son los que trae por defecto weblogic.

Tras muchas pruebas, el útlimo jar que vi que daba problemas era wsdl4j-1.6.2.jar, que excluyéndolo elimina el aviso.

El total de exclusiones en el pom.xml de Maven es el siguiente:


 <dependency>  
      <groupId>org.apache.axis2</groupId>  
      <artifactId>axis2-kernel</artifactId>  
      <version>1.4.1</version>  
      <exclusions>  
           <exclusion>  
                <groupId>org.apache.geronimo.specs</groupId>  
                <artifactId>geronimo-activation_1.1_spec</artifactId>  
           </exclusion>  
           <exclusion>  
                <groupId>org.apache.geronimo.specs</groupId>  
                <artifactId>geronimo-javamail_1.4_spec</artifactId>  
           </exclusion>  
           <exclusion>  
                <groupId>org.apache.geronimo.specs</groupId>  
                <artifactId>geronimo-jms_1.1_spec</artifactId>  
           </exclusion>  
           <exclusion>  
                <groupId>org.apache.geronimo.specs</groupId>  
                <artifactId>geronimo-stax-api_1.0_spec</artifactId>  
           </exclusion>  
           <exclusion>  
                <groupId>javax.activation</groupId>  
                <artifactId>activation</artifactId>  
           </exclusion>  
           <exclusion>  
                <artifactId>wsdl4j</artifactId>  
                <groupId>wsdl4j</groupId>  
           </exclusion>  
      </exclusions>  
 </dependency>  
 <dependency>  
      <groupId>org.apache.axis2</groupId>  
      <artifactId>axis2-codegen</artifactId>  
      <version>1.4.1</version>  
      <exclusions>  
           <exclusion>            
                <groupId>org.apache.geronimo.specs</groupId>  
                <artifactId>geronimo-activation_1.1_spec</artifactId>  
           </exclusion>  
           <exclusion>  
                <groupId>org.apache.geronimo.specs</groupId>  
                <artifactId>geronimo-stax-api_1.0_spec</artifactId>  
           </exclusion>                 
      </exclusions>  
 </dependency>  

viernes, 9 de agosto de 2013

Comprobar si sesion serializable cluster / Check Session Serializable cluster

Cuando se trabaja con aplicaciones web que van a ejecutarse en varios nodos de un cluster, una de las cosas que hay que tener en cuenta es que todo objeto que se almacene en sesión debe ser serializable.

Esto es debido a que el gestor del cluster va a serializarla para repartirla entre los distintos nodos. Así, ante la caída de uno de ellos, el balanceador de carga puede redireccionar al usuario hacia otro nodo conservando todos los datos de sesión, por ejemplo el contexto de spring security.

Un objeto es serializable cuando:
  1. Implementa el interface java.io.serializable
  2. Todas sus propiedades también son serializables

Para comprobar si un objeto es serializable, lo mejor es intentar serializarlo. Si salta una excepción entonces es que tenemos algo mal.

A continuación se muestra un trozo de código que lee todos los objetos de sesión y los serializa a un fichero de texto. Para mayor seguridad, seguidamente intenta leerlos de ese fichero.
Si este código no da error, entonces la sesión es serializable y no habrá problemas con los cluster.

 private void checkSession(HttpSession session) {  
   final String RUTA = "C:/MyDir/session.ser";  
   File f = new File(RUTA);  
   f.delete();  
   try {  
        FileOutputStream fileOut = new FileOutputStream(RUTA);  
        ObjectOutputStream out = new ObjectOutputStream(fileOut);  
        String nombreAtributo;  
        @SuppressWarnings("rawtypes")  
        Enumeration enumNombres = session.getAttributeNames();  
        while (enumNombres.hasMoreElements()) {  
             nombreAtributo = (String) enumNombres.nextElement();  
             System.out.println("Serializando... " + nombreAtributo);  
             out.writeObject(session.getAttribute(nombreAtributo));  
        }  
        out.flush();  
        out.close();  
        fileOut.close();  
        System.out.printf("Todo ok");  
   } catch (IOException e) {  
           System.out.println("No serializable!!!!");  
           e.printStackTrace();  
   }  
   //****************************************//  
   FileInputStream fileIn = null;  
   ObjectInputStream in = null;  
   try {  
        fileIn = new FileInputStream(RUTA);  
        in = new ObjectInputStream(fileIn);  
        Object objeto;          
        while (true){  
             objeto = in.readObject();  
             System.out.println("Deserializando...." + objeto.getClass() + " -----> " + objeto);  
        }                                
   }  
   catch (EOFException exc) {  
        try {  
             in.close();  
             fileIn.close();  
        } catch (IOException e) {                        
             e.printStackTrace();  
        }                        
   }  
   catch (IOException i) {  
           i.printStackTrace();  
   }   
   catch (ClassNotFoundException e) {  
           e.printStackTrace();  
   }  
 }  

Este código se puede poner en cualquier parte de la aplicación que tenga acceso a la request. Por ejemplo, en Spring MVC se podría usar en un controller, un interceptor o incluso en un filtro.

lunes, 5 de agosto de 2013

Cargar certificado de fichero / Load certificate from file

 String ruta = "C:/miDir/test.crt"; 
 CertificateFactory cf = CertificateFactory.getInstance("X.509"); 
 BufferedInputStream in = new BufferedInputStream(new FileInputStream(ruta)); 
 java.security.cert.Certificate cert = cf.generateCertificate(in); 

Forzar a utilizar la última versión de Internet Explorer

A partir de Explorer 8 se incluyen las vistas de compatibilidad, que permiten mostrar una página como si se emplease Explorer 7.

Para forzar a utilizar siempre la última versión disponible hay que incluir la siguiente meta e la cabecera


 <meta http-equiv="X-UA-Compatible" content="IE=Edge" />  

domingo, 4 de agosto de 2013

Aplicar filtrado Maven en applicationContext

En casi todas las aplicaciones web, a la hora de plantearse el desarrollo es necesario tener en cuenta los distintos entornos en los que se desplegará (Test, Preproducción y Producción, entre otros). Habrá ciertas variables que dependerán de estos entornos, como rutas o algunos parámetros de configuración que habrá que ir actualizando a medida que se hacen los pases.

Una forma sencilla de hacer esto es emplear los filter de maven. Su uso más extendido es el aplicado a los resources de la aplicación, pero también se pueden emplear en el webapp de las aplicaciones web.

En este ejemplo se va a cambiar un parámetro dentro del applicationContext.xml de Spring. Esto también se puede hacer empleando el Expresion Language de Spring y el conf.properties, aunque aquí se hará con filters Maven.

Necesitamos:
  • Uno o mas profiles donde indicar el fichero que contendrá las variables
  • Añadir la sección de filters indicando qué fichero emplear
  • Plugin de resources
  • Configurar war plugin para filtrar el webapp
  • Emplear la variable en el applicationContext

En el pom.xml declaramos los profiles, en los que se especifica en qué ruta está el fichero que contiene las variables a sustituir:


<profiles>
    <!-- Development environment -->
    <profile>
       <id>development</id>
       <activation>
          <activeByDefault>true</activeByDefault>
       </activation>
       <properties>
           <filters.ficheroProperties>src/dev/filters/desarrollo- env.properties</filters.ficheroProperties>
       </properties>
    </profile>
</profiles>


Esto simplemente declara la variable filters.ficheroProperties con el src/dev/filters/desarrollo-env.properties, cuando se emplee el profile devolpment (en este caso es por defecto). Aquí se añadiría un profile por cada entorno y a la hora de generar los wars habría que usar el parámetro -P referenciando el que correspondiese.

Este fichero será un properties corriente:

mavenProperty.jdbc = jdbc/miDatasource


Dentro del apartado de build, se declaran el fichero que contiene las variables de filtrado. Es aquí donde se usa la variable declarada en el profile, a fin de que cambie en cada entorno.


<!-- Se le indica de qué ficheros se obtienen los valores de las variables que se reemplazan -->
<filters>
      <filter>${filters.ficheroProperties}</filter>
</filters>



En el apartado de plugins, se añade el maven-resources-plugin:

<!-- Plugin para gestionar los resources y el filtrado -->
<plugin>    
       <groupId>org.apache.maven.plugins</groupId>
       <artifactId>maven-resources-plugin</artifactId>
       <version>2.4.3</version>
       <configuration>
            <encoding>UTF-8</encoding>
      </configuration>
</plugin>


También en el apartado de plugins, se añade configuración extra al maven-war-plugin:


<plugin>    
     <groupId>org.apache.maven.plugins</groupId>
     <artifactId>maven-war-plugin</artifactId>
     <version>2.3</version>
        <configuration>
           <!-- Configurar filtrado de ficheros dentro del webapp -->
           <webResources>
             <resource>
              <filtering>true</filtering>
              <directory>src/main/webapp/WEB-INF</directory>
              <includes>
                 <include>**/*.xml</include>
              </includes>
            </resource>
          </webResources>
      </configuration>
</plugin>


En este último plugin se indica que se van a filtrar los recursos dentro de WEB-INF cuya extensión sea .xml. De este modo, a la hora de componer el war se van a leer todos los ficheros xml de este directorio buscando variables Maven para reemplazar.


Por último, basta con emplear las variables declaradas en el fichero de properties dentro del applicationContext.xml

<bean id="dataSource" class="org.springframework.jndi.JndiObjectFactoryBean">
    <property name="jndiName" value="${mavenProperty.jdbc}" />
</bean>


Configuración del SSL de apache

Para poder acceder con certificado digital, el servidor será el encargado de pedir el certificado del cliente (two ways SSL), validarlo y enviárselo a weblogic a través del plugin activado (se encapsula como un parámetro más de la request).
Para realizar estas tareas se necesita lo siguiente:
  • Un certificado de servidor:
    • Clave privada.
    • Clave pública.
  • Una lista de autoridades de certificación en el servidor.
  • Añadir la configuración necesaria

Certificado de servidor

Se necesita un certificado para identificar al servidor, separando por un lado su clave de firma y por otro la parte pública del certificado. Para generalo se pueden seguir los siguientes pasos, empleando KeyStoreExplorer (También se pude hacer con OpenSSL):
  • Crear nuevo keystore
  • Generar nuevo par de claves
    • Rellenar la información de identificación
  • Exportar la clave privada (Server.key)
  • Exportar el certificado en formato PEM (Server.pem)

Lista de autoridades de certificación en el servidor

En el punto anterior configuramos la identidad del servidor. Ahora se añade la lista de CAs que usará para validar los certificados de los clientes. Cuando tenga que autenticar a un cliente, leerá el certificado del navegador y comprobará si está firmado por una de las CAs en las que confía, para aceptarlo o rechazarlo.
La lista de CAs que siempre deberá tener son:
  • Certificado raíz de la FNMT
  • Certificado raíz de la policía.
    • Se descargan tanto el raíz como las tres subordinadas.
    • Otras CAs de las que se disponga
    • CA propia para confiar en nuestros propios certificados

 - CAs oficiales

Una vez se descargan los certificados, para obtener su formato PEM se puede usar el keyStoreExplorer, añadiéndolos a un keystore y luego exportándolos como se hizo con el certificado de servidor, o directamente usando el editor de certificados de windows.
Al final obtenemos los archivos en formato .cer, que se pueden abrir directamente con un editor de texto y comprobar que es el formato PEM codificado en base 64.

- Otras CAs de las que se disponga

También se pueden añadir otras CAS que hayan firmado certificados de pruebas de los que ya se dispongan.
En este caso, basta con abrir el certificado en formato p12 pfx con el KeyStoreExplorer y seleccionar la CA (es el primer certificado de la jerarquía). Luego se copia su representación PEM, que será la propia CA que nos interesa.

- CA propia para firmar certificados

Para crear una CA se usará el programa OPENSSL para windows.
Los primero que hay que hacer es crear las claves de la entidad certificadora, que será la que genere el resto de certificados. Se ejecuta la siguiente instrucción:
openssl req -x509 -newkey rsa:2048 -keyout cakey.pem -days 3650 -out cacert.pem

Lo que significa que estamos creando una nueva entidad que generará certificados X509 con algoritmo de encriptación rsa de 2048 bytes. Generará la clave privada de la entidad en el fichero cakey.pem y la clave publica en el cacert.pem.
El parámetro -days con 3650 indica que la entidad certificadora no expirará en 10 años.
Nos pedirá una contraseña para nuestra entidad certificadora, que es muy importante no perder. Nos pedirá también una serie de datos (País, Nombre de Empresa…), que nos identifica como entidad certificadora.

Poniéndolo todo en conjunto

En este punto ya tenemos:
  • Clave de servidor: Server.key
  • Certificado de servidor: Server.pem
  • Ficheros sueltos de CAs de policía y FNMT
  • Ficheros sueltos de otras CAs de certificados.
  • Fichero de nuestra propia CA: cacert.pem
Las CAs deben estar en un único fichero, así que se crea uno nuevo (cas.pem) y se concatena en éste el contenido de todos los anteriores, copiando y pegando. Al final quedará algo del estilo:
-----BEGIN CERTIFICATE-----
MIIC+TCCAmKgAwIBAgIENvEbGTANBgkqhkiG9w0BAQUFADA2MQswCQYDVQQGEwJF
...
LwVMZGACokIeb4ZoZVUO2ENv8pExPqNHPCgFr0W2nSJMJntLfVsV+RlG3whd
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
MIIFvzCCA6egAwIBAgIQAMUmyW4QlO1DT/e1+2eflDANBgkqhkiG9w0BAQsFADBd
....
Rua2628QZv5yKZL45hMDN4MviTN3QnzB5XillEH4avjfG9Q=
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
....

Estos tres ficheros se meten en el directorio \ssl.crt dentro del directorio de configuración de Apache.
En el directorio de configuración de Apache, se crea un fichero ssl.conf que, haciendo uso de estos tres fichero, configurará el SSL del servidor. También se indican una serie de parámetros sobre los protocolos aceptados y demás opciones.

#=================================================
# SSL/TLS para los vhosts
# =================================================
SSLEngine On
SSLProtocol -all +TLSv1 +SSLv3
SSLCipherSuite ALL:!ADH:!EXPORT56:RC4+RSA:+HIGH:+MEDIUM:!EXP:!eNULL:!aNULL:!LOW
SSLCertificateFile conf/ssl.crt/server.pem
SSLCertificateKeyFile conf/ssl.crt/server.key
SSLCACertificateFile conf/ssl.crt/cas.pem
SSLInsecureRenegotiation on
SSLOptions +StdEnvVars +ExportCertData
LogLevel debug

Mostrar favicon.ico en proyecto web maven

Para mostrar el favicon en un proyecto maven, éste se debe ubicar en en webapp/resources, junto con el resto de imágenes, css, etc.. Pero el navegado lo va a buscar por defecto directamente al contexto base www.midireccion.es/miContexto/favicon.ico.
Para indicarle que vaya a resources hay que incluir la siguiente meta en el head de todas las páginas:

<link rel="shortcut icon" type="image/x-icon" href="${pageContext.request.contextPath}/resources/favicon.ico" />