Translate

lunes, 20 de junio de 2011

Configuracion con Oracle RAC 10g y 11g

Recientemente he tenido la oportunidad de configurar Alfresco contra un Oracle RAC. Además la suerte ha sido doble porque inicialmente se configuró contra un RAC de 10g y posteriormente se ha migrado a un 11g, con lo cual hemos podido comprobar el funcionamiento en ambas versiones.

De cara a Alfresco el tema del RAC es transparente ya que los cambios de configuración se realizan a nivel del driver de conexión. Vamos a ver la configuración utilizada:


db.name=alfresco
db.username=alfresco
db.password=alfresco
db.driver=oracle.jdbc.OracleDriver
db.url=jdbc:oracle:thin:@(DESCRIPTION=(LOAD_BALANCE=on)(ADDRESS=(PROTOCOL=TCP)(HOST=nodo1-vip.red.dominio.es)(PORT=1521))(ADDRESS=(PROTOCOL=TCP)(HOST=nodo2-vip.red.dominio.es)(PORT=1521))(CONNECT_DATA=(SERVICE_NAME=LAN_APLICACIONES.red.dominio.es)))
db.pool.validate.query=SELECT 1 FROM DUAL
hibernate.default_schema=ALFRESCO
El cambio para Oracle RAC está en la cadena de conexión. Vamos a ver uno a uno los parámetros de esta cadena de conexión:

DESCRIPTION 
contiene el descriptor de conexión, es decir todos los parámetros que se van a usar para conectar. En este caso teniamos el RAC con 2 nodos con lo cual solo teniamos un único descriptor. Sería posible para instalaciones mas complejas tener una lista de descriptores y cada descriptor a su vez con varios servidores. Por ejemplo:

(DESCRIPTION_LIST=
  (DESCRIPTION= 
   (ADDRESS=(protocol_address_information))
   (ADDRESS=(protocol_address_information))
   (ADDRESS=(protocol_address_information))
   (CONNECT_DATA= 
     (SERVICE_NAME=service_name)))
  (DESCRIPTION= 
   (ADDRESS=(protocol_address_information))
   (ADDRESS=(protocol_address_information))
   (ADDRESS=(protocol_address_information))
   (CONNECT_DATA= 
     (SERVICE_NAME=service_name))))

LOAD_BALANCE
Indica si se van a usar las direcciones de forma aleatoria (activo) o de forma secuencial (desactivado). Se puede especificar cualquiera de estos valores que podemos encontrar en diferentes ejemplos:
on | off | yes | no | true | false
ADDRESS contiene el PROTOCOL, ADDRESS, PORT
que se explican por si mismas

CONNECT_DATA contiene la identificación del servicio .

SERVICE_NAME
En este caso no estamos usando un SID, el cual apuntaría solo a uno de los nodos, si no que se define un servicio a nivel de Oracle y se apunta contra este.

Es posible que nos encontremos ejemplos en los que en la cadena de conexión aparece también el parámetro FAILOVER. Este parámetro esta por defecto activado para los descriptores así que no será necesario incluirlo a no ser que queramos desactivarlo.

Desde el servidor podemos ver como las conexiones se empiezan a balancear entre los nodos:


[tomcat]# lsof -nPi |grep 1521
tnslsnr   22544   oracle   11u  IPv6  996133       TCP *:1521 (LISTEN)
jsvc      28316 alfresco  231u  IPv6 1026752       TCP 172.17.1.154:55223->172.17.31.23:1521 (ESTABLISHED)
jsvc      28316 alfresco  232u  IPv6 1026753       TCP 172.17.1.154:55224->172.17.31.23:1521 (ESTABLISHED)
jsvc      28316 alfresco  233u  IPv6 1026754       TCP 172.17.1.154:55667->172.17.31.21:1521 (ESTABLISHED)
jsvc      28316 alfresco  234u  IPv6 1026755       TCP 172.17.1.154:55226->172.17.31.23:1521 (ESTABLISHED)
jsvc      28316 alfresco  235u  IPv6 1026756       TCP 172.17.1.154:55227->172.17.31.23:1521 (ESTABLISHED)
jsvc      28316 alfresco  236u  IPv6 1026757       TCP 172.17.1.154:55228->172.17.31.23:1521 (ESTABLISHED)
jsvc      28316 alfresco  237u  IPv6 1026758       TCP 172.17.1.154:55671->172.17.31.21:1521 (ESTABLISHED)
jsvc      28316 alfresco  238u  IPv6 1026759       TCP 172.17.1.154:55230->172.17.31.23:1521 (ESTABLISHED)
jsvc      28316 alfresco  239u  IPv6 1026760       TCP 172.17.1.154:55231->172.17.31.23:1521 (ESTABLISHED)


Es importante recordar que el esquema para el parámetro hibernate.default_schema se debe incluir siempre en mayúsculas, ya que de otro modo el primer arranque funcionará correctamente pero en el segundo recibiriamos un error de Schema upgrade failed


http://download.oracle.com/docs/cd/B28359_01/network.111/b28317/tnsnames.htm

http://wiki.alfresco.com/wiki/Database_Configuration#Oracle_example

miércoles, 15 de junio de 2011

Bug: Read only y renombrar licencia

Como reza en el JIRA de Alfresco

http://issues.alfresco.com/jira/browse/ALF-7487


Era muy común en las versiones enterprise que de vez en cuando se perdiera la licencia y el repositorio se pusiera en modo lectura. La solución siempre habia sido renombrar la licencia de *.installed a *.lic

Como se puede ver en JIRA, el bug se ha "solucionado" en la 3.4.2, lo pongo entre comillas porque el problema aparece pero con otra cara. Esta vez el repositorio no se queda en read-only pero aparece un warning en el log:

 16:10:38,215 WARN [service.descriptor.DescriptorService] unexpected exception caught and ignored  
 de.schlichtherle.xml.GenericCertificateIntegrityException  
 at de.schlichtherle.xml.GenericCertificate.verify(Unknown Source)  
 at de.schlichtherle.license.LicenseNotary.verify(Unknown Source)  
 at de.schlichtherle.license.LicenseManager.verify(Unknown Source)  
 at de.schlichtherle.license.ftp.LicenseManager.verify(Unknown Source)  
 at org.alfresco.enterprise.license.AlfrescoLicenseManager.verify(AlfrescoLicenseManager.java:148)  
 at de.schlichtherle.license.LicenseManager.verify(Unknown Source)  
 at org.alfresco.enterprise.license.LicenseComponent$1.execute(LicenseComponent.java:147)  
 at org.alfresco.enterprise.license.LicenseComponent$1.execute(LicenseComponent.java:141)  
 at org.alfresco.repo.transaction.RetryingTransactionHelper.doInTransaction(RetryingTransactionHelper.java:381)  
 at org.alfresco.enterprise.license.LicenseComponent$2.doWork(LicenseComponent.java:201)  
 at org.alfresco.enterprise.license.LicenseComponent$2.doWork(LicenseComponent.java:198)  
 at org.alfresco.repo.security.authentication.AuthenticationUtil.runAs(AuthenticationUtil.java:508)  
 at org.alfresco.enterprise.license.LicenseComponent.verify(LicenseComponent.java:197)  
 at org.alfresco.enterprise.license.LicenseComponent.verifyLicense(LicenseComponent.java:101)  
 at org.alfresco.repo.descriptor.DescriptorServiceImpl$1$2.execute(DescriptorServiceImpl.java:206)  
 at org.alfresco.repo.descriptor.DescriptorServiceImpl$1$2.execute(DescriptorServiceImpl.java:199)  
 at org.alfresco.repo.transaction.RetryingTransactionHelper.doInTransaction(RetryingTransactionHelper.java:381)  
 at org.alfresco.repo.descriptor.DescriptorServiceImpl$1.doWork(DescriptorServiceImpl.java:197)  
 at org.alfresco.repo.security.authentication.AuthenticationUtil.runAs(AuthenticationUtil.java:508)  
 at org.alfresco.repo.descriptor.DescriptorServiceImpl.onBootstrap(DescriptorServiceImpl.java:162)  
 at org.springframework.extensions.surf.util.AbstractLifecycleBean.onApplicationEvent(AbstractLifecycleBean.java:56)  
 at org.springframework.context.event.SimpleApplicationEventMulticaster.multicastEvent(SimpleApplicationEventMulticaste  
 r.java:97)  
 at org.alfresco.repo.management.SafeApplicationEventMulticaster.multicastEvent(SafeApplicationEventMulticaster.java:78  
 )  
 at org.springframework.context.support.AbstractApplicationContext.publishEvent(AbstractApplicationContext.java:294)  
 at org.springframework.context.support.AbstractApplicationContext.finishRefresh(AbstractApplicationContext.java:858)  
 at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:419)  
 at org.springframework.web.context.ContextLoader.createWebApplicationContext(ContextLoader.java:261)  
 at org.springframework.web.context.ContextLoader.initWebApplicationContext(ContextLoader.java:192)  
 at org.springframework.web.context.ContextLoaderListener.contextInitialized(ContextLoaderListener.java:47)  
 at org.alfresco.web.app.ContextLoaderListener.contextInitialized(ContextLoaderListener.java:63)  
 at org.apache.catalina.core.StandardContext.listenerStart(StandardContext.java:3843)  
 at org.apache.catalina.core.StandardContext.start(StandardContext.java:4342)  
 at org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:791)  
 at org.apache.catalina.core.ContainerBase.addChild(ContainerBase.java:771)  
 at org.apache.catalina.core.StandardHost.addChild(StandardHost.java:525)  
 at org.apache.catalina.startup.HostConfig.deployDescriptor(HostConfig.java:627)  
 at org.apache.catalina.startup.HostConfig.deployDescriptors(HostConfig.java:553)  
 at org.apache.catalina.startup.HostConfig.deployApps(HostConfig.java:488)  
 at org.apache.catalina.startup.HostConfig.start(HostConfig.java:1149)  
 at org.apache.catalina.startup.HostConfig.lifecycleEvent(HostConfig.java:311)  
 at org.apache.catalina.util.LifecycleSupport.fireLifecycleEvent(LifecycleSupport.java:117)  
 at org.apache.catalina.core.ContainerBase.start(ContainerBase.java:1053)  
 at org.apache.catalina.core.StandardHost.start(StandardHost.java:719)  
 at org.apache.catalina.core.ContainerBase.start(ContainerBase.java:1045)  
 at org.apache.catalina.core.StandardEngine.start(StandardEngine.java:443)  
 at org.apache.catalina.core.StandardService.start(StandardService.java:516)  
 at org.apache.catalina.core.StandardServer.start(StandardServer.java:710)  
 at org.apache.catalina.startup.Catalina.start(Catalina.java:578)  
 at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)  
 at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)  
 at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)  
 at java.lang.reflect.Method.invoke(Method.java:597)  
 at org.apache.catalina.startup.Bootstrap.start(Bootstrap.java:288)  
 at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)  
 at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)  
 at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)  
 at java.lang.reflect.Method.invoke(Method.java:597)  
 at org.apache.commons.daemon.support.DaemonLoader.start(DaemonLoader.java:177)  

La solución como en el caso anterior es la misma, renombrar el fichero .lic a .installed

martes, 14 de junio de 2011

Importación masiva con Alfresco Bulk Filesystem import

La entrada de hoy es para explicar como funciona el módulo Alfresco Bulk Filesystem import desarrollado por Peter Monks. Este módulo nos va a permitir importar un conjunto de ficheros permitiendonos incorporar metadatos en el proceso.

Alfresco trae varios mecanismos para importar contenidos:

En todos los casos anteriores necesitamos crear reglas o los mecanismos necesarios usando la API para asignar los metadatos.

Mediante el módulo simplemente creando un fichero con el mismo nombre que el original pero con la extension metadata.properties hará que se lea su contenido y se incorporen los metadatos de forma dinámica.

Por ejemplo, tengo un documento que llamado Documentación.odf y otro Documentación.metadata.properties ubicado en el mismo directorio

Dentro del fichero properties se pondrá el tipo de contenido y cada uno de los metadatos:

  # tipo de contenido
  type=cm:content
  # Aspectos
  aspects=cm:versionable, custom:myAspect
  # Propiedades
  cm\:title=This is the value of the cm:title field.
  cm\:description=This is the value of the cm:description field.
  # Enlace a un tag (es necesario apuntar a la referencia)
  cm\:taggable=workspace://SpacesStore/3da6c395-3a4b-4a57-836d-8e5
  # Propiedad personalizada de nuestro modelo de datos:
  custom\:myProperty=This is the value of the custom:myProperty field.
  # Propiedad con multiples valores
  custom\:mvProperty=first value,second value,third value.
  # Fechas (sólo formato ISO8601)
  cm\:created=2011-06-15T10:00:01.234+01:00
  cm\:modified=2011-06-15T10:00:01.234+01:00
Otra de las ventajas de las que se habla es que la importación mediante este metodo es mucho más rápida, ya que nos ahorramos el overhead de los protocolos y estamos cargando los datos desde un disco local, así que me he decidido a comprobarlo por mi mismo

He subido a alfresco mediante FTP y utilizando Filezilla configurado para subir los ficheros de 1 en 1, (haciéndolo de 2 en dos tuve fallos en varios ficheros y fue más lento).

El tiempo para subir 1,4Gb de datos distribuidos en 679 ficheros fue de 4:24 segundos. Esto sin haber asignado ningún metadato.

A continuación y para poder realizar la prueba con metadatos de forma rápida me situé en la carpeta donde se habían subido los documentos (/opt/alfresco34/alf_data/contentstore/2011/6/14/12) y con un pequeño script cree los ficheros de metadatos introduciendo únicamente el tipo de contenido:

# for i in `find . -type f` ;do echo "type=cm:content" > $i.metadata.properties;done
De esta manera he podido crear  de una forma muy rápida todos los ficheros. He usado el contenido del contentstore porque sabemos que los nombres en el contenstore no tienen espacios, y el miniscript me dio algún problema con los ficheros que tenían espacios en los nombres. El módulo es muy sensible a fallos, si no existe algún fichero de metadatos no se ejecutará.

He comprobado además que en la carpeta del contentstore únicamente están los archivos cargados por FTP y que los nuevos se van a copiar en la hora siguiente.

Ya tenemos los ficheros a subir con sus metadatos. Con la importación del módulo se añade un web-script que nos ofrece una página desde donde podemos iniciar la importación masiva en Alfresco y monitorizar todo el proceso. En mi caso localhost (ojo de no poner barra al final!!):

http://localhost:8080/alfresco/service/bulk/import/filesystem


En esta pantalla pondremos donde se encuentran los ficheros que queremos importar. Esto ha de ser una ruta en el sistema de ficheros y puede ser local o estar montada de forma remota.

El siguiente campo es donde queremos que se ubiquen los ficheros. La página usa Ajax y nos ayudará a auto completar este campo, lo que resulta muy útil.

Una vez lanzada la importación veremos como va el progreso


El resultado fue que se subieron los ficheros en 2 minutos 39 segundos, casi la mitad de tiempo. No está nada mal.

Como nota final,  mencionar que es posible incorporar metadatos a ficheros que ya existen en Alfresco simplemente poniendo los ficheros de metadatos.

ACTUALIZACIÓN:

El formato del fichero de metadatos ya no es un fichero de texto plano, si no que se ha pasado al formato xml para dar un mejor soporte a carácteres unicode. El formato que sigue es:


  <?xml version="1.0" encoding="UTF-8"?>
  <!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd">
  <properties>
    <entry key="key1">value1</entry>
    <entry key="key2">value2</entry>
    ...
  </properties>


Más información

http://blogs.alfresco.com/wp/pmonks/2009/10/22/bulk-import-from-a-filesystem/
http://code.google.com/p/alfresco-bulk-filesystem-import/

jueves, 9 de junio de 2011

Alfresco 4.0 en SVN

Cual ha sido mi sorpresa que al intentar acceder a los nightly builds de Alfresco http://dev.alfresco.com/downloads/nightly/dist/ llevaban desde el dia 19 de Abril sin actualizarse. Un rápido aviso a Jeff Potts hizo que se arreglara esto para poder utilizar la última versión del SVN sin necesidad de tener que bajar el código fuente y compilarlo

Hoy me ha llegado un correo informandome de que ya estaba solucionada y cuando accedo.. Sorpresa: Alfresco 4.0

Si quereis probarlo solo teneis que descargarlo desde:
 
http://wiki.alfresco.com/wiki/Nightly_Community_Build

Tened en cuenta que lo que se haya para descargar no ha pasado por QA y por tanto es posible que haya errores. Por ejemplo en la versión del día de hoy falta una coma en el script /webapps/alfresco/WEB-INF/classes/alfresco/dbscripts/create/org.hibernate.dialect.MySQLInnoDBDialect/AlfrescoCreate-RepoTables.sql

Las novedades a primera vista son muy considerables y parecen orientadas a hacerlo todo mucho más sencillo:
  • Ayudas contextuales 
  • Posibilidad de arrastrar documentos al navegador para subirlos.
  • Simplificación de los sites con elementos configurables mediante dashelts (ya no tenemos wiki y blog por defecto, solo los añadiremos si los necesitamos)
  • Posibilidad de subida de ficheros de configuración al diccionario de datos de tareas programadas, acciones..
ACTUALIZADO: con la nueva versión ya disponible oficialmente. Información sobre las novedades en la siguiente presentación:

http://www.slideshare.net/alfresco/get-ready-for-alfresco-40

miércoles, 1 de junio de 2011

Nuevas funcionalidades en Share preparadas

Leo en la web de Jeff Potts  que @schminke ha públicado unos screencasts de las nuevas funcionalidades de Alfresco Share que ya están en el subversion pero que todavía no están en la última release 3.4e

Para poder probar estas funcionalidades es necesario hacer un CheckOut desde subversion.

Se espera que la próxima release que incluya estas funcionalidades saldrá a final de Verano o principios de Otoño

EDITADO: Debido a problemas de ancho de banda se pueden encontrar las screencasts aquí:
http://www.schminkel.de/alfresco-blog/alfresco-35.html