27 de diciembre de 2017

:: Javascript. Creando el juego de Piedra, Papel, Tijera

Únicamente y como prueba de concepto, crearemos el juego de Piedra, Papel, Tijera, que permita jugar varias partidas (por ejemplo 3) y que muestre el resultado de cada partida.

El código podría ser algo similar a este:
var juego=function(jugador1, jugador2){
  var jugadaJugador1=jugador1.jugar();
  var jugadaJugador2=jugador2.jugar();
  
  //Definimos las reglas del juego
  var reglasJuego={
    piedra:"tijera",papel:"piedra",tijera:"papel"
  }
  
  //Determina quien gana la partida
  if(jugadaJugador1===jugadaJugador2){
    return "Empate";
  }
  if (jugadaJugador1===reglasJuego[jugadaJugador2]){
    return jugador1.nombre+" gana";
  }else{
    return jugador2.nombre+" gana";
  }
}

function Jugador(nombreJugador){
  var valores=['piedra', 'papel', 'tijera'];
  this.nombre=nombreJugador;
  //Devuelve un valor aleatorio entre 0 y 2
  this.jugar= function(){
    return valores[Math.floor(Math.random()*valores.length)];
  }
}
  
var jugador1=new Jugador('Pablo');
var jugador2=new Jugador('Luis');

for(var i=0;i<10 code="" console.log="" i="" juego="" jugador1="" jugador2="">

La salida de este pequeño ejemplo podría ser algo similar a esto:
"Pablo gana"
"Luis gana"
"Luis gana"
"Empate"
"Empate"
"Empate"
"Pablo gana"
"Pablo gana"
"Luis gana"
"Pablo gana"

22 de diciembre de 2017

:: Alfresco. Deshabilitar CSRF (Tip)

El filtro Cross-Site Request Forgery (CSRF) viene por defecto habilitado en Alfresco, pero en ocasiones puede que necesitemos deshabilitarlo.

Para ello, debemos quitar los comentarios a unas líneas en nuestro fichero: "share-config-custom.xml" ubicado en: "shared/classes/alfresco/web-extension/"; en concreto, las líneas son las siguientes:
< config condition="CSRFPolicy" evaluator="string-compare" replace="true" >
      < filter >
   < /filter >
< /config >

Más información: http://docs.alfresco.com/5.2/concepts/csrf-policy.html

17 de diciembre de 2017

:: Alfresco. Cómo desplegar un workflow

Tras le desarrollo de un workflow en Activity, podemos llevar a cabo el despliegue de este de distintas maneras.
Describiremos a continuación cómo tenemos estructurado el workflow.

En la ruta "shared/classes/alfresco/extension/" tenemos el fichero de contexto.
Fichero: activiti-adhoc-timer-workflow-context.xml

<?xml version='1.0' encoding='UTF-8'?>
<!DOCTYPE beans PUBLIC '-//SPRING//DTD BEAN//EN' 'http://www.springframework.org/dtd/spring-beans.dtd'>

<beans>
    <bean id="lifecycle.workflowBootstrap" parent="workflowDeployer">
  <property name="workflowDefinitions">
   <list>
    <props>
     <prop key="engineId">activiti</prop>
     <prop key="location">alfresco/extension/activiti-adhoc-timer.bpmn20.xml</prop>
     <prop key="mimetype">text/xml</prop>
     <prop key="redeploy">false</prop>
    </props>
   </list>
  </property>
  <property name="labels">
   <list>
                <value>alfresco/extension/activiti-adhoc-timer-messages</value>
   </list>
  </property>
 </bean>
</beans>

Tendremos un fichero con los literales utilizados, en la siguiente ruta: "shared/classes/alfresco/web-extension/messages/".
Fichero: activiti-adhoc-timer-messages.properties

# For Activiti Timer Workflow Example
activitiAdhocTimer.workflow.title=Activiti Adhoc Timer 
activitiAdhocTimer.workflow.description=Activiti Adhoc Timer Sample Process 

La propia definición del workflow la hemos ubicado en la siguiente carpeta, referenciada desde el fichero de contexto: "shared/classes/alfresco/extension/workflow/".
Fichero: activiti-adhoc-timer.bpmn20.xml

<?xml version="1.0" encoding="UTF-8" ?>

<definitions id="adhoc-definitions"
             typeLanguage="http://www.w3.org/2001/XMLSchema"
             expressionLanguage="http://www.w3.org/1999/XPath"
             targetNamespace="http://activiti.org/bpmn20" 
             xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xmlns:activiti="http://activiti.org/bpmn">

    <process id="activitiAdhocTimer" name="Activiti Timer Adhoc">

        <startEvent id="start"
            activiti:formKey="wf:submitAdhocTask" />

        <sequenceFlow id='flow1' 
            sourceRef='start'
            targetRef='adhocTask' />

        <userTask id="adhocTask" name="Urgent task"
            activiti:formKey="wf:adhocTask">
           <extensionElements>
               <activiti:taskListener event="create" class="org.alfresco.repo.workflow.activiti.tasklistener.ScriptTaskListener">
                  <activiti:field name="script">
                     <activiti:string>
                      if (typeof bpm_workflowDueDate != 'undefined') task.setVariableLocal('bpm_dueDate', bpm_workflowDueDate);
                      if (typeof bpm_workflowPriority != 'undefined') task.priority = bpm_workflowPriority;
                     </activiti:string>
                  </activiti:field>
               </activiti:taskListener>
           </extensionElements>
            <humanPerformer>
                <resourceAssignmentExpression>
                    <formalExpression>${bpm_assignee.properties.userName}</formalExpression>
                </resourceAssignmentExpression>
            </humanPerformer>
        </userTask>
        
        <!-- Boundry event attached to 'adhocTask', which will end the task after 1 minute -->
        <boundaryEvent id="timer" cancelActivity="true" attachedToRef="adhocTask" name="testTimer">
     <timerEventDefinition>
      <!-- ISO-8601 durations of one hour-->
      <timeDuration>PT1H</timeDuration>
    </timerEventDefinition>
  </boundaryEvent>   

        <sequenceFlow id='flow2' 
        sourceRef='adhocTask'
            targetRef='taskDone' />

        <userTask id="taskDone" name="Urgent task completed on time"
            activiti:formKey="wf:completedAdhocTask" >
            <documentation>
                The urgent task was completed on time by ${bpm_assignee.properties.userName}.
            </documentation>
            <extensionElements>
               <activiti:taskListener event="create" class="org.alfresco.repo.workflow.activiti.tasklistener.ScriptTaskListener">
                  <activiti:field name="script">
                     <activiti:string>
                        if (typeof bpm_workflowDueDate != 'undefined') task.setVariableLocal('bpm_dueDate', bpm_workflowDueDate);
                        if (typeof bpm_workflowPriority != 'undefined') task.priority = bpm_workflowPriority;
                     </activiti:string>
                  </activiti:field>
               </activiti:taskListener>
           </extensionElements>
            <humanPerformer>
                <resourceAssignmentExpression>
                    <formalExpression>${initiator.properties.userName}</formalExpression>
                </resourceAssignmentExpression>
            </humanPerformer>
        </userTask>
        
        <userTask id="taskExpired" name="Urgent task expired"
            activiti:formKey="wf:completedAdhocTask" >
            <documentation>
                The urgent task was NOT completed on time by ${bpm_assignee.properties.userName}.
            </documentation>
            <extensionElements>
               <activiti:taskListener event="create" class="org.alfresco.repo.workflow.activiti.tasklistener.ScriptTaskListener">
                  <activiti:field name="script">
                     <activiti:string>
                        if (typeof bpm_workflowDueDate != 'undefined') task.setVariableLocal('bpm_dueDate', bpm_workflowDueDate);
                        if (typeof bpm_workflowPriority != 'undefined') task.priority = bpm_workflowPriority;
                     </activiti:string>
                  </activiti:field>
               </activiti:taskListener>
           </extensionElements>
            <humanPerformer>
                <resourceAssignmentExpression>
                    <formalExpression>${initiator.properties.userName}</formalExpression>
                </resourceAssignmentExpression>
            </humanPerformer>
        </userTask>

        <sequenceFlow id='flow3' sourceRef='taskDone'
            targetRef='theEnd' /> 
        
        <sequenceFlow id='flow4' sourceRef='timer'
            targetRef='taskExpired' />
        
         <sequenceFlow id='veryLongTimer' sourceRef='taskExpired'
            targetRef='theEnd' />

        <endEvent id="theEnd" />
    </process>
</definitions>

Una opción sería que ante cualquier reinicio del servicio se volviera a re-desplegar el workflow, para lo que tendríamos que modificar la propiedades del fichero de contexto "activiti-adhoc-timer-workflow-context.xml":
< prop key="redeploy" >true< /prop >
Otra opción posible sería hacer uso de la consola de administración de flujos de trabajo. Inicialmente podemos ver los workflows desplegados mediante la intrucción:
show definitions


El acceso a esta consola se realiza por medio de la url siguiente: http://servidor:puerto/alfresco/s/admin/admin-communitysummary
O bien: http://localhost:8181/alfresco/
Seleccionar la entrada: Alfresco Administration Console

Para proceder al despliegue, la instrucción sería:
deploy activiti alfresco/extension/workflow/activiti-adhoc-timer.bpmn20.xml


Por defecto el motor activiti viene habilitado, pero en el caso de que necesitásemos otro motor, podríamos añadir las siguientes líneas en el fichero "alfresco-global.properties"
## Activity
system.workflow.engine.activiti.enabled=true
system.workflow.engine.activiti.definitions.visible=true

En el caso de utilizar JBPM, las entradas a definir serían:
### JBPM
system.workflow.engine.jbpm.enabled=true
system.workflow.engine.jbpm.definitions.visible=true


12 de diciembre de 2017

:: Alfresco. Importación masiva de documentos

Alfresco dispone de una utilidad para llevar a cabo la importación masiva de documentos, esta está accesible en la siguiente url:


http://localhost:8383/alfresco/service/bulkfsimport


Los campos que deberemos cumplimentar son los siguientes:

Import directory
Directorio desde el que realizaremos la importación (ficheros a importar en nuestro Alfresco)

Por ejemplo: d:\software
Target space
Path
Ruta -dentro de nuestro Alfresco- al nodo (carpeta) sobre la que se realizará la importación

Por ejemplo: /Espacio de empresa/Sitios/netic360/documentLibrary/Inicio
NodeRef
Referencia al nodo sobre el que queremos importar (por ejemplo carpeta dentro de nuestro Alfresco) 
Por ejemplo: workspace://SpacesStore/844bc038-53f5-4a79-b06e-941c1b8302c1
Disable rules
Nos permitirá - si es necesario - habilitar/deshabilitar la ejecución de reglas, lo que podría ralentizar la carga masiva

Replace existing files
Marcando esta opción reemplazará los ficheros existentes con los que están siendo importados

Batch size
Es el nº de directorio y ficheros que serán importados de una sola vez
Por ejemplo: 10
Number of threads
Número de hilos de ejecución
Por ejemplo: 5

Para comprobar el estado de importación podemos acceder a la url:

http://localhost:8383/alfresco/service/bulkfsimport/status

Para obtener el path o el NodeRef es útil hacer uso de las "Herramientas de administración" > "Navegador de Nodos".

7 de diciembre de 2017

:: Alfresco. Creación de una lista de datos

En este caso, la prueba de concepto será la creación de un tipo personalizado, en concreto una lista de datos. Para ello, seguiremos los siguientes pasos:


.- Seleccionaremos la opción: "Herramientas administrativas" > "Gestor de modelos" (disponible en la versión 5.2)

.- Crearemos un nuevo modelo, cumplimentando los datos del formulario:
Espacio de nombres: http://www.alfresco.org/model/publicaciones2/1.0
Prefijo: publi2
Nombre: Publicaciones2

.- Tras cumplimentar los datos, crearemos los distintos campos a contemplar en la lista. Desde el gestor de modelos no permite la creación heredando del padre "dlListItem" por lo que una vez creado el modelo, lo exportaremos (.zip) y modificaremos los ficheros oportunos con los valores orrespondientes.


 .- Importaremos el modelo con las modificaciones, y ya tendremos a nuestra disposición la nueva lista de datos

El tipo de datos definido está compuesto por dos ficheros cuyo contenido es el siguiente:
Fichero: publicaciones2.xml
< ?xml version="1.0" encoding="UTF-8" ?>
< model xmlns="http://www.alfresco.org/model/dictionary/1.0" name="publi2:Publicaciones2" >
< description >Gestionar publicaciones< /description >
< author >neTIC360< /author >
< imports >
< import uri="http://www.alfresco.org/model/datalist/1.0" prefix="dl" />
< import uri="http://www.alfresco.org/model/dictionary/1.0" prefix="d" />
< /imports>
< namespaces>
< namespace uri="http://www.alfresco.org/model/publicaciones2/1.0" prefix="publi2" />
< /namespaces >
< data-types />
< constraints />
< types >
< type name="publi2:Publicaciones2" >
< title >Publicaciones neTIC360< /title >
< description >Listas de datos de Publicaciones< /description >
< parent >dl:dataListItem< /parent >
< properties >
< property name="publi2:titulo" >
< title >Título< /title >
< type >d:text< /type >
< mandatory >true< /mandatory >
< index enabled="true" >
< tokenised >TRUE< /tokenised >
< facetable >true< /facetable >
< /index >
< /property >
< property name="publi2:autor" >
< title >Autor< /title >
< type >d:text< /type >
< mandatory >false< /mandatory >
< index enabled="true" >
< tokenised >TRUE< /tokenised >
< facetable >false< /facetable >
< /index >
< /property >
< property name="publi2:isbn" >
< title >ISBN
< type >d:text< /type >
< mandatory >false< /mandatory >
< index enabled="true" >
< tokenised >TRUE< /tokenised >
< facetable >false< /facetable >
< /index >
< /property >
< /properties >
< associations />
< overrides />
< mandatory-aspects />
< /type >
< /types >
< aspects />
< /model >



Fichero: CMM_publicaciones2_Model.xml
< ?xml version="1.0" encoding="UTF-8"? >< module >
< id >CMM_Publicaciones2< /id >
< auto-deploy >true< /auto-deploy >
< configurations >


< config condition="DocumentLibrary" evaluator="string-compare" replace="false" >
< types >
< type name="dl:dataListItem" >
< subtype label="" name="publi2:Publicaciones2" />

< /types >
< /config >


< config condition="publi2:Publicaciones2" evaluator="node-type" >
< forms >
< form >
< field-visibility >
< show force="true" id="dl:title" />
< /field-visibility >
< appearance >
< set appearance="whitespace" id="publi2:Publicaciones2_cmm_set0" />
< field id="dl:title" set="publi2:Publicaciones2_cmm_set0" >
< /field >
< /appearance >
< /form >


< form id="doclib-simple-metadata" >
< edit-form template="../documentlibrary/forms/doclib-simple-metadata.ftl" />
< field-visibility >
< show force="true" id="dl:title" />
< /field-visibility >
< appearance >
< set appearance="whitespace" id="publi2:Publicaciones2_cmm_set0" />
< field id="dl:title" set="publi2:Publicaciones2_cmm_set0" >
< /field >
< /appearance >
< /form >


< form id="doclib-inline-edit" >
< field-visibility>
< show id="dl:name" />
< show force="true" id="dl:content" />
< show force="true" id="dl:title" />
< show force="true" id="dl:description" />
< /field-visibility >
< appearance >
< field id="dl:name" >
< control >
< control-param name="maxLength" >255< /control-param >
< /control >
< /field >
< field id="dl:title" >
< control template="/org/alfresco/components/form/controls/textfield.ftl" />
< /field >
< field id="dl:content" label-id="" >
< control>
< control-param name="editorAppearance" >explorer< /control-param >
< control-param name="forceEditor" >true< /control-param >
< /control >
< /field >
< /appearance >
< /form >
< /forms >
< /config >




< config condition="FormDefinition" evaluator="string-compare" >
< form-definition id="Publicaciones2">[{"elementconfig":{"label":"","appearance":"bordered-panel"},"pseudonym":"cmm/editor/layout/1cols","label":"cmm.form-editor.palette.one-column","type":["layout"],"column":[{"pseudonym":"cmm/editor/property/text","id":"cm:title","elementconfig":{"infoname":"cm:title","infolabel":"Título","infotype":"d:text","force":true},"label":"Título [cm:title]","type":["property"]}]}]< /form-definition >
< /config >
< /configurations >
< /module >

30 de noviembre de 2017

:: Sombras en CSS

En CSS3 podemos establecer sombras sobre diversos elementos por medio de "text-shadow" y "box-shadow".
Un sencillo ejemplo de su uso sería el siguiente:
< !DOCTYPE html >
< html lang="es" >
< head >
< meta charset="UTF-8" >
< title >Text Shadow y Box Shadow< /title >
< style >
body{
font-family: trebuchet ms;
display: flex;
justify-content: space-around;
flex-direction: column;
margin: 40px;
}
h1{
color: #000;
text-shadow: 0 0 20px #dadada;
}
input{
font-size: 1em;
background-color: #fff;
border: 1px solid #dcdcdc;
border-radius: 5px;
padding: 8px;
width: 400px;
box-shadow: 0 0 20px #dedede;
}
div {
padding: 20px;
background-color: #333;
color: #ddd;
width: 300px;
font-size: 1em;
box-shadow: 0 0 20px #dcdcdc;
border-radius: 5px;
}
< /style >
< /head >
< body >
< h1 >Texto con sombra< /h1 >
< br />
< input type="text" placeholder="Introduzca un valor" />
< br />
< div >Efecto sobre una capa< /div >
< /body >
< /html >


La salida del código anterior sería algo como esto:


24 de noviembre de 2017

:: Liferay. Configurando urlrewrite

Para llevar a cabo esta tarea, Liferay utiliza una libreria de "tuckey" de forma similar al mod-rewrite de Apache. Esta librería nos permite tener un sistema de gestión de redirecciones en las fases iniciales de procesado de peticiones.

El filtro que viene configurado por defecto en el fichero: "liferay-web.xml" es el siguiente:
< filter > < filter-name >URL Rewrite Filter< /filter-name > < filter-class >com.liferay.portal.servlet.filters.urlrewrite.UrlRewriteFilter< /filter-class > < init-param > < param-name >logLevel< /param-name > < param-value >ERROR< /param-value > < /init-param > < init-param > < param-name >statusEnabled< /param-name > < param-value >false< /param-value > < /init-param > < init-param > < param-name >url-regex-ignore-pattern< /param-name > < param-value >(^/combo/)|(^/html/.+\.(css|gif|html|ico|jpg|js|png)(\?.*)?$)< /param-value > < /init-param > < /filter >
En este mismo fichero podría llevarse a cabo la siguiente modificación para evitar que se procese el filtro con cada una de las peticiones realizadas a nuestro portal.
De esta manera, para evitar que ejecute peticiones innecesarias podemos modificar la expresión regular por la siguiente:

< param-value >(^/combo/)|(^/image/)|(^/document/)|(^.*\.(css|gif|html|ico|jpg|js|png|woff|ttf|eot|bmp).*)|(^/html/.+\.(css|gif|html|ico|jpg|js|png)(\?.*)?$)< /param-value >

Más información: http://tuckey.org/urlrewrite/

17 de noviembre de 2017

:: Esquema SMS

El esquema SMS permite mostrar una pantalla para enviar un SMS desde nuestras aplicaciones web.
< a href="sms:+34 123456789?body=SMS desde la web" >Envíanos un SMS< /a >

El enlace anterior mostraría la opción de enviar un SMS con el texto: "SMS desde la web".

De todas formas, es necesario señalar que no todos los dispositivos soportan el parámetro "?body". Por ejemplo, en IOS no podemos especificar este parámetro para que el SMS aparezca con el cuerpo ya cumplimentado y tendremos que llevar a cabo esta tarea de manera manual.

12 de noviembre de 2017

:: Alfresco. Obtener los mimetypes definidos (Tip)

En Alfresco 5.2 podemos consultar los mimetypes definidos invocando la siguiente url:


http://{Alfresco}/alfresco/s/mimetypes
http://localhost:8383/alfresco/s/mimetypes?mimetype=* (Obtendremos las transformaciones disponibles)



Obtendremos un listado con los tipos definidos en nuestra instalación de Alfresco (simpre que tengamos permisos para llevar a cabo esta llamada):


De esta manera podemos obtener los detalles sobre las posibles conversiones soportadas por Alfresco.

9 de noviembre de 2017

:: Traducir textos desde Excel (Tip)

En ocasiones necesitamos llevar a cabo traducciones de un ficheros de recursos, y aunque lo normal es contratar un servicio de traducción profesional, para aquellos proyectos en los que no importe demasiado o bien se desee realizar las traducciones con Google Translate, una opción sería utilizar Excel para automatizar este proceso.



Los pasos a seguir serían:
1.- Crear una hoja excel en Google Drive
2.- En la columna A insertaremos los términos a traducir (uno por fila)
3.- En la columna B1 insertaremos la fórmula siguiente, por ejemplo para traducir del español al inglés:

=GOOGLETRANSLATE(A1;"ES";"EN");

4.- Aplicaremos esta misma fórmula al resto de celdas de la columna

De esta manera tendremos los términos traducidos de una manera rápida.

7 de noviembre de 2017

:: CSS. Reseteo de estilos

Es habitual que para resetear los estilos CSS cuando vamos a desarrollar un tema, utilizar el selector global: "*". Por ejemplo:
*{
margin:0;
padding:0;
}


Aunque es correcto, quizás podría utilizarse una opción no tan drástica:
/* http://meyerweb.com/eric/tools/css/reset/
v2.0 | 20110126
License: none (public domain)
*/

html, body, div, span, applet, object, iframe,
h1, h2, h3, h4, h5, h6, p, blockquote, pre,
a, abbr, acronym, address, big, cite, code,
del, dfn, em, img, ins, kbd, q, s, samp,
small, strike, strong, sub, sup, tt, var,
b, u, i, center,
dl, dt, dd, ol, ul, li,
fieldset, form, label, legend,
table, caption, tbody, tfoot, thead, tr, th, td,
article, aside, canvas, details, embed,
figure, figcaption, footer, header, hgroup,
menu, nav, output, ruby, section, summary,
time, mark, audio, video {
margin: 0;
padding: 0;
border: 0;
font-size: 100%;
font: inherit;
vertical-align: baseline;
}
/* HTML5 display-role reset for older browsers */
article, aside, details, figcaption, figure,
footer, header, hgroup, menu, nav, section {
display: block;
}
body {
line-height: 1;
}
ol, ul {
list-style: none;
}
blockquote, q {
quotes: none;
}
blockquote:before, blockquote:after,
q:before, q:after {
content: '';
content: none;
}
table {
border-collapse: collapse;
border-spacing: 0;
}

El objetivo de las hojas de estilo "reset" es reducir las inconsistencias del navegador correspondientes a la altura de las líneas, márgenes y tamaños de fuentes de los encabezados, y muchas otras cosas.

Los estilos anteriores son muy genéricos; por ejemplo no hay ningún color establecido para el body. Este CSS da únicamente unas pautas a seguir, pero deberíamos adaptarlo a cada caso particular, por ejemplo definiendo, colores de la página, enlaces,...

Más información: https://meyerweb.com/eric/tools/css/reset/

27 de octubre de 2017

:: Alfresco. Establecer cuotas de disco para los usuarios. Javascript API

En Alfresco (5.2), podríamos establecer cuotas de disco para todos los usuarios mediante el uso de la API Javascript de Alfresco, de la siguiente manera:




Habilitar las cuotas de disco en el fichero alfresco-global.properties mediante la línea:
system.usages.enabled=true
Para establecer la cuota de disco para nuevos usuarios, tendríamos que añadir en el mismo fichero alfresco-global.properties la línea: system.content.maximumFileSizeLimit=10240000
Para los usuarios ya creados, tendríamos que ejecutar el siguiente script:
var nodes = people.getPeople(null);
for each(var node in nodes)
{
user = utils.getNodeFromString(node);
if (user)
{
people.setQuota(user,"10240000");
}
}


A continuación podríamos acceder al perfil de un usuario para comprobar que efectivamente se le ha establecido una cuota de 10MB.


Más información sobre Javascript API: http://docs.alfresco.com/community/references/API-JS-getPeople.html (Alfresco 201704)

26 de octubre de 2017

:: Alfresco API REST. Discovery

Por medio de la API REST de Alfresco -en su versión 5.2- podemos realizar una petición a la url para obtener información detallada de nuestra instancia de Alfresco instalada.


http://{Alfresco}/alfresco/api/discovery
Tras la llamada a esta url, obtendremos toda la información disponible en formato JSON.
En nuestro caso, los detalles del repositorio son los siguientes:

{
"entry": {
"repository": {
"edition": "Community",
"version": {
"major": "5",
"minor": "2",
"patch": "0",
"hotfix": "0",
"schema": 10005,
"label": "r135134-b14",
"display": "5.2.0.0 (r135134-b14) schema 10005"
},
"status": {
"isReadOnly": false,
"isAuditEnabled": true,
"isQuickShareEnabled": true,
"isThumbnailGenerationEnabled": true
},
"modules": [{
"id": "alfresco-aos-module",
"title": "Alfresco Office Services Module",
"description": "Allows applications that can talk to a SharePoint server to talk to your Alfresco installation",
"version": "1.1.5",
"installDate": "2017-03-08T17:15:12.218+0000",
"installState": "INSTALLED",
"versionMin": "5.1",
"versionMax": "999"
}, {
"id": "org.alfresco.integrations.google.docs",
"title": "Alfresco / Google Docs Integration",
"description": "The Repository side artifacts of the Alfresco / Google Docs Integration.",
"version": "3.0.3",
"installDate": "2017-03-08T17:15:16.134+0000",
"installState": "INSTALLED",
"versionMin": "5.0.0",
"versionMax": "5.99.99"
}, {
"id": "org_alfresco_module_wcmquickstart",
"title": "Web Quick Start",
"description": "Web Quick Start",
"version": "5.2.e",
"installDate": "2017-03-08T17:15:17.950+0000",
"installState": "INSTALLED",
"versionMin": "3.3",
"versionMax": "999"
}, {
"id": "alfresco-share-services",
"title": "Alfresco Share Services AMP",
"description": "Module to be applied to alfresco.war, containing APIs for Alfresco Share",
"version": "5.2.0",
"installDate": "2017-03-08T17:15:17.029+0000",
"installState": "INSTALLED",
"versionMin": "5.1",
"versionMax": "999"
}, {
"id": "alfresco-trashcan-cleaner",
"title": "alfresco-trashcan-cleaner project",
"description": "The Alfresco Trash Can Cleaner (Alfresco Module)",
"version": "2.2",
"installState": "UNKNOWN",
"versionMin": "0",
"versionMax": "999"
}
]
}
}
}


Es otra forma más de obtener información detallada de nuestro Alfresco.

20 de octubre de 2017

:: Alfresco. Crear webscript para listar carpetas

La siguiente prueba de concepto consistirá en la creación de un webscript que liste las carpetas contenidas en una carpeta dada, pasada como parámetro.


Descriptor
Crearemos un primer lugar el descriptor, al que llamaremos "dir.get.desc.xml" con el siguiente contenido:
< webscript >
< shortname >Listado de carpetas< /shortname >
< description >WebScript para listar carpetas< /description >
< url >/dir/{folderpath}?verbose={verbose}< /url >
< format default="html">extension< /format >
< authentication >user< /authentication >
< /webscript >


Plantilla
En segundo lugar crearemos la plantilla, a la que llamaremos "dir.get.html.ftl" con el siguiente contenido:
< html >
< head >
< title >Carpeta ${folder.displayPath}/${folder.name}< /title >
< /head >
< body >
< p >Alfresco ${server.edition} Edición v${server.version} : dir< /p >
< p >Contenidos de la carpeta ${folder.displayPath}/${folder.name}< /p >
< table >
< #list folder.children as child >
< tr >
< td >< #if child.isContainer>d< /#if >< /td >
< #if verbose>
< td >${child.properties.modifier}< /td >
< td ><#if child.isDocument >
${child.properties.content.size}< /#if >< /td >
< td >${child.properties.modified?date}< /td >
< /#if >
< td >${child.name}< /td >
< /tr >
< /#list >
< /table >
< /body >
< /html >


Controlador
Por último crearemos el controlador, al que llamaremos "dir.get.js" con el siguiente contenido:
// Listado de carpetas a partir de la carpeta pasada como parámetro
var verbose = (args.verbose == "true" ? true : false);
var folderpath = url.templateArgs.folderpath;

// Busca las carpetas dentro del repositorio
var folder = roothome.childByNamePath(folderpath);

// Comprueba que la carpeta ha sido encontrada
if (folder == undefined || !folder.isContainer) {
status.code = 404;
status.message = "Folder " + folderpath + " not found.";
status.redirect = true;
}

// Construye el modelo para mostrar la respuesta
model.verbose = verbose;
model.folder = folder;




Accederemos a la siguiente url para actualizar la lista de webscripts disponibles:
"http://{alfresco}/alfresco/service/index" y pulsaremos sobre el botón "Refresh WebScripts"

Si todo está correcto podremos hacer una llamada a nuestro webscripts, invocando la siguiente url: "http://{alfresco}/alfresco/service/dir/Espacio%20de%20empresa?verbose=true"

Como resultado obtendremos un listado similar a este:






15 de octubre de 2017

:: Alfresco. Añadir vistas a la biblioteca de documentos

En Alfresco 5.2 para el caso de que necesitemos añadir nuevas vistas a la biblioteca de documentos, seguiremos los pasos siguientes:



1.- Añadiremos al fichero "share-config-custom.xml" ubicado en la siguiente ruta: "{Alfresco}\tomcat\shared\classes\alfresco\web-extension" < view-renderer iconclass="table" id="minimalist" index="60" label="button.view.minimalist" widget="Alfresco.DocumentListTableViewRenderer" >

< js src="components/documentlibrary/documentlist-view-simple.js" />
< js src="components/documentlibrary/documentlist-view-table.js" />
< css src="components/documentlibrary/documentlist-view-table.css" />
< /dependencies >
< json-config >
{
"actions": {
"show": "false"
},
"indicators": {
"show": "false"
},
"selector": {
"show": "true"
},
"thumbnail": {
"show": "false"
},
"propertyColumns": [
{
"property": "cm:name",
"label": "table.minimalist.label.name",
"link": "true"
}
]
}
< /json-config >
< /view-renderer >


2.- Para incluir los nuevos literales de traducción que necesitaremos, debemos copiar y/o editar el fichero: "mycustom.properties" ubicado en: "{Alfresco}\tomcat\shared\classes\alfresco\web-extension\messages"

# Vistas (minimalista)
button.view.minimalist=Minimalista
table.minimalist.label.name=Nombre




3.- Reiniciaremos el servicio de Alfresco y si todo es correcto, tendremos a nuestra disposición las nuevas vistas definidas

10 de octubre de 2017

:: Alfresco. Número de elementos por página

El Alfresco 5.2, por defecto el número de elementos por página a la hora de listar documentos es 50.
Supongamos que en nuestro caso necesitásemos que el nº de elementos por página fuera 10. Para ello, seguiremos los siguientes pasos:

1.- Copiar el fichero: "documentlist-v2.get.js" to "{Alfresco}\tomcat\shared\classes\alfresco\web-extension\site-webscripts\org\alfresco\components\documentlibrary"

2.- En este fichero tenemos que añadir la siguiente línea:
model.widgets[1].options.pageSize = 10;

3.- Esta línea tendremos que añadirla al final del código de la función "widgets":

function widgets()
{
   var useTitle = "true";
   var docLibConfig = config.scoped["DocumentLibrary"];
   if (docLibConfig != null)
   {
      var tmp = docLibConfig["use-title"];
      useTitle = tmp != null ? tmp : "true";
   }

   var docListToolbar = {
      id: "DocListToolbar",
      name: "Alfresco.DocListToolbar",
      assignTo: "docListToolbar",
      options: {
         siteId: (page.url.templateArgs.site != null) ? page.url.templateArgs.site : "",
         rootNode: toolbar.rootNode != null ? toolbar.rootNode : "",
         repositoryRoot: toolbar.rootNode,
         hideNavBar: Boolean(toolbar.preferences.hideNavBar),
         repositoryBrowsing: toolbar.rootNode != null,
         useTitle: (useTitle == "true"),
         syncMode: toolbar.syncMode != null ? toolbar.syncMode : "",
         createContentByTemplateEnabled: model.createContentByTemplateEnabled,
         createContentActions: model.createContent
      }
   };
 
   var documentList = {
      id : "DocumentList",
      name : "Alfresco.DocumentList",
      options : {
         syncMode : model.syncMode != null ? model.syncMode : "",      
         siteId : (page.url.templateArgs.site != null) ? page.url.templateArgs.site : "",
         containerId : template.properties.container != null ? template.properties.container : "documentLibrary",
         rootNode : model.rootNode != null ? model.rootNode : "null",
         repositoryRoot : model.rootNode,
         usePagination : (args.pagination == "true"),
         sortAscending : (model.preferences.sortAscending != null ? model.preferences.sortAscending : true),
         sortField : model.preferences.sortField != null ? model.preferences.sortField : "cm:name",
         showFolders : (model.preferences.showFolders != null ? model.preferences.showFolders : true),
         hideNavBar: (model.preferences.hideNavBar != null ? model.preferences.hideNavBar : false),
         simpleView : model.preferences.simpleView != null ? model.preferences.simpleView : "null",
         viewRenderers: model.viewRenderers,
         viewRendererName : model.preferences.viewRendererName != null ? model.preferences.viewRendererName : "detailed",
         viewRendererNames : model.viewRendererNames != null ? model.viewRendererNames : ["simple", "detailed", "gallery", "filmstrip"],
         highlightFile : page.url.args["file"] != null ? page.url.args["file"] : "",
         replicationUrlMapping : model.replicationUrlMapping != null ? model.replicationUrlMapping : "{}",
         repositoryBrowsing : model.rootNode != null,
         useTitle : (model.useTitle != null ? model.useTitle == "true" : true),
         userIsSiteManager : model.userIsSiteManager,
         associatedToolbar: { _alfValue: "docListToolbar", _alfType: "REFERENCE" },
         commonComponentStyle : model.commonComponentStyle,
         suppressComponent : model.suppressComponent,
         filmstripImageLazyLoading: model.filmstripImageLazyLoading == "true"
      }
   };
   if (model.repositoryUrl != null)
   {
      documentList.options.repositoryUrl = model.repositoryUrl;
   }

   model.widgets = [docListToolbar, documentList];
   model.widgets[1].options.pageSize = 10;
}

4.- En este caso, como se puede ver, hemos establecido el valor a 10 elementos por página

5.- Reiniciaremos el servicio de Alfresco y tras esto la nueva configuración estará disponible, mostrando 10 elementos por página



5 de octubre de 2017

:: Alfresco. Contar el número de documentos en una carpeta desde CMIS

CMIS no soporta la cláusula COUNT en las consultas, pero en cualquier caso podemos realizar una consulta para determinar el nº de documentos de una determinada carpeta.


Aunque este no es el mejor método, aquí va un ejemplo:

SELECT cmis:objectId FROM cmis:document where IN_TREE('2a9c2dfe-eeb0-481a-9c68-d4c214abdeb2');

30 de septiembre de 2017

:: Alfresco. Obtener información sobre tipos de datos definidos (Tip)

Una forma rápida y sencilla de obtener información sobre el diccionario de datos definidos en Alfresco, consiste en realizar una petición a la siguiente url:


http://localhost:8080/alfresco/service/api/dictionary


Tras solicitarnos las credenciales de acceso para un usuario autorizados, obtendremos un fichero json con toda la información.

Este tip podría sernos de utilidad por ejemplo para obtener el tipo padre del que hereda un tipo personalizado de datos que hayamos definido.

25 de septiembre de 2017

:: Alfresco. Limitar el número de intentos de login

En las últimas versiones de Alfresco (5.2) se incluye la posibilidad de limitar el número de intentos fallidos durante el proceso de login, lo que ayudará a protegerse contra ataques de fuerza bruta.

Para habilitar esta característica debemos añadir las siguientes líneas en el fichero "alfresco-global.properties":

authentication.protection.limit=3
authentication.protection.periodSeconds=5
authentication.protection.enabled=true


De esta manera el número de intentos fallidos al loguearnos en la plataforma es de 3, con una latencia entre intentos de 5 segundos.


18 de septiembre de 2017

:: Alfresco. Refresco de las etiquetas (Tip)

Quizás en alguna ocasión has etiquetado documentos y al realizar un filtro por las etiquetas que indican que están asociadas a algún documento obtenemos el mensaje: "No hay elementos de contenido".

Esto podría ser debido a que se ha eliminado un documento con esa etiqueta, y ha quedado en la papelera (no se ha eliminado definitivamente). Si tras eliminar el contenido de la papelera y refrescar, el problema persiste, podríamos -mediante un script- intentar refrescar las etiquetas.

var refresh = actions.create('refresh-tagscope');
refresh.execute(space);


Este script podríamos ejecutarlo de manera manual sobre un sitio para obligar a que la propiedad cm:tagScopeSummary (puede ser consultado a través del navegador de nodos) se actualice cada vez que se asigne una etiqueta de un documento en un sitio.

13 de septiembre de 2017

:: Alfresco. Convertir documento a PDF desde un script

A continuación describiremos cómo llevar a cabo la conversión de un documento (por ejemplo docx) a formato PDF desde un script de Alfresco, creando -además- una nueva versión de este.

El planteamiento podría ser el siguiente:

1.- Crearemos un script al que llamaremos "convert_pdf.js" y que ubicaremos en: "Repositorio>Diccionario de datos>Scripts" con el siguiente contenido:

var pdfNode=document.transformDocument("application/pdf");
var version=document.createVersion("version pdf",true); //true=create major version
document.properties.content.write(pdfNode.properties.content,true,false);
document.name+=".pdf";
document.save();
pdfNode.remove();


2.- Crearemos una carpeta sobre la que llevaremos a cabo esta prueba de concepto, y que denominaremos: "Word a PDF"

3.- Sobre esta carpeta que acabamos de crear, definiremos una regla de contenido:
- Cuando: se crean o entran elementos en esta carpeta
- Si se cumplen todos los criterios: Todos los elementos
- Realizar acción: Ejecutar script - convert_pdf.js

4.- Cada vez que subamos un documento a esta carpeta, se ejecutará el script de conversión a PDF, y se creará una nueva versión del documento


Como podemos ver en la imagen anterior, se ha realizado correctamente la conversión a PDF y se ha generado una nueva versión del documento.

7 de septiembre de 2017

:: Alfresco. Realizar una búsqueda sobre una carpeta concreta de Alfresco (Tip)

Si bien este tipo de búsqueda no es posible realizarlo desde la interfaz de Alfresco, podemos -desde el navegador de nodos- lanzar una consulta.
Por ejemplo, utilizando la sintaxis CMIS, la consulta podría ser algo así:

SELECT cmis:name FROM cmis:document WHERE IN_FOLDER('id_carpeta')

Mediante la consulta anterior buscaremos todos los documentos que se encuentren dentro de la carpeta cuyo identificador especifiquemos. Este identificador podemos consultarlo cuando accedemos a los detalles de las propiedades, por ejemplo:"ba7d9c8b-48dd-4b90-bf30-73fc4e38b03d"

El resultado de la consulta -en nuestro Alfresco- sería:

27 de agosto de 2017

:: Alfresco. Añadir nuevas vistas a la biblioteca de documentos

A la hora de mostrar las entradas de la biblioteca de documentos disponemos de varias vistas (sencilla, detallada, galería,...) pero es posible añadir otras vistas adicionales.


Por ejemplo, en el caso de que necesitásemos añadir la "Vista de efectividad" podemos consultar el fichero siguiente: "$ALF_HOME/tomcat/webapps/share/WEB-INF/classes/alfresco/share-documentlibrary-config.xml" donde viene como ejemplo.



Copiaremos el siguiente código al fichero: "$ALF_HOME/tomcat/shared/classes/alfresco/web-extension/share-config-custom.xml":

< view-renderer iconclass="table" id="effectivity" index="90" label="button.view.effectivity" widget="Alfresco.DocumentListTableViewRenderer" >
< dependencies >
< js src="components/documentlibrary/documentlist-view-detailed.js" >< /js>
< js src="components/documentlibrary/documentlist-view-table.js" >< /js>
< css src="components/documentlibrary/documentlist-view-table.css" >< /css>
< /dependencies >
< json-config >
{
"actions": {
"show": "true"
},
"indicators": {
"show": "true"
},
"selector": {
"show": "true"
},
"thumbnail": {
"show": "true"
},
"propertyColumns": [
{
"property": "name",
"label": "table.effectivity.label.name",
"width": "300"
},
{
"property": "cm:description",
"label": "table.effectivity.label.description"
},
{
"property": "version",
"label": "table.effectivity.label.version",
"width": "50"
},
{
"property": "cm:modified",
"label": "table.effectivity.label.modified",
"width": "100"
},
{
"property": "cm:modifier",
"label": "table.effectivity.label.modifier",
"width": "100"
},
{
"property": "cm:from",
"label": "table.effectivity.label.from",
"width": "100"
},
{
"property": "cm:to",
"label": "table.effectivity.label.to",
"width": "100"
}
]
}
< /json-config >
< /view-renderer >

El codigo anterior debemos envolverlo entre las siguientes etiquetas:
< config condition="DocumentLibraryViews" evaluator="string-compare" >
< view-renderers >
..........
..........
< /view-renderers >
< /config >


A continuación accederemos a la siguiente url para que los cambios se hagan efectivos: http://localhost:8383/share/service/index y pulsaremos sobre el botón "Refresh webscripts".



En caso de que no veamos la nueva vista en nuestro Alfresco, podemos reiniciar el servicio.

21 de agosto de 2017

:: MySQL. Habilitar el log

Por defecto el log de MySQL se encuentra des-habilitado.
En ocasiones necesitamos habilitarlo por diversos motivos, por ejemplo para realizar tareas de depuración, pero ¿cómo lo hacemos?

Para llevar a cabo esta tarea debemos seguir los pasos siguientes:

.- Ejecutamos la siguiente consulta para determinar los valores que tiene establecidos el log de MySQL

show variables like 'general_log%';


.- Establecemos el log a "ON" con la siguiente consulta
set global general_log=1;

En el caso de que necesitemos consultar el log, este se encuentra en la ruta devuelta por la primera consulta ejecutada. Será del tipo:
C:\xampp\mysql\data\nombre_del_equipo.log

14 de agosto de 2017

:: Oracle. Cómo saber el conjunto de caracteres configurado

Aunque se trata este de un "tip"sencillo, en alguna ocasión hemos necesitado comprobar o asegurarnos del código de caracteres configurado en la base de datos Oracle con la que trabajamos.
Este valor configurado en la base de datos determina el conjunto de caracteres que puede almacenarse en ella.

La información sobre este conjunto de caracteres se almacena en la tabla de diccionario de datos denominada: "SYS.PROPS$".

De esta forma, para comprobar una serie de parámetros de nuestra base de datos, podríamos ejecutar la siguiente consulta:

SELECT * FROM NLS_DATABASE_PARAMETERS;

El valor devuelto, podría ser algo similar a lo siguiente:


10 de agosto de 2017

:: Alfresco. Descriptor de un dashlet (Tip)

El descriptor de un webscript correspondiente a un dashlet es como cualquier otro descriptor, excepto por el parámetro: "familia".

< webscript > < shortname>Hola mundo Dashlet< /shortname > < description>Saludo al usuario< /description > < family>user-dashlet< /family > < url >/components/dashlets/holamundodashlet< /url >

Este parámetro puede ser de los tres tipos siguientes:

  • user-dashlet: Es un webscript que implementa un dashlet que puede ser añadido en el panel del usuario
  • site-dashlet: Es un webscript que implementa un dashlet que puede ser añadido al panel del sitio
  • dashlet: Es un webscript que implementa un dashlet que puede ser añadido en cualquier panel


3 de agosto de 2017

:: Alfresco. User dashlet

En una entrada anterior -y a modo de prueba de concepto- habíamos explicado brevemente cómo desarrollar un dashlet webscript sencillo, que mostraba un mensaje.
Respecto a la entrada anterior, únicamente modificaremos una línea "user-dashlet" en lugar de "site-dashlet".

¿Cómo realizar un dashlet sencillo (webscript dashlet)?
1.- Crearemos un fichero denominado "holamundodashlet.get.desc.xml" con el siguiente contenido
<webscript>
    <shortname>Dashlet de ejemplo</shortname>
    <description>Dashlet de ejemplo que muestra un literal</description>
    <family>user-dashlet</family>
      <url>/components/dashlets/holamundodashlet</url>
</webscript>
2.- Crearemos un fichero denominado "holamundodashlet.get.html.ftl" con el siguiente contenido
<div class="dashlet">
<div class="title" >Dashlet de ejemplo</div>
<div class="body" >Mensaje mostrado en el dashlet</div>
</div>
3.- Estos ficheros los copiamos en la ruta "tomcat/shared/classes/alfresco/web-extension/site-webscripts/org/alfresco/components/dashlets"

4.- Reiniciamos el servicio y si no existen errores tendremos a nuestra disposición un nuevo dashlet

Para comprobar el correcto funcionamiento, y puesto que se trata de un "dashlet de usuario", accederemos al panel de inicio y en la rueda dentada que aparece en la parte superior derecha seleccionaremos la opción "Personalizar el panel de inicio".


Pulsaremos sobre el botón: "Añadir dashlets" y seleccionaremos el que hemos desarrollado, y pulsaremos sobre el botón: "Aceptar".

22 de julio de 2017

:: Velocity. Notación de referencias silenciosa

Cuando Velocity encuentra una referencia indefinida, el comportamiento por defecto es el de escribir el nombre de la referencia. Por ejemplo:.
<input name="correo" type="text" value="$correo"/>
Cuando el formulario se carga por primera vez la referencia $correo no tiene valor. En este caso quizás preferiríamos que se mostrase un texto en blanco en lugar del literal: "$correo". Usando la notación de referencias silenciosa, se obviará el comportamiento normal de Velocity.

De esta manera, en lugar de utilizar $correo en la plantilla Velocity, utilizaríamos $!correo. Con esta modificación el ejemplo anterior quedaría así:
<input name="correo" type="text" value="$!correo"/>
Ahora cuando el formulario se carga por primera vez y $correo no tenga valor una cadena vacía se escribirá en lugar de "$correo".

Igualmente, la notación formal y la silenciosa pueden ser utilizadas conjuntamente:
<input name="correo" type="text" value="$!{correo}"/>

17 de julio de 2017

:: Liferay. Tipos de página

A la hora de crear páginas en Liferay, las alternativas que este CMS (gestor de contenidos) pone a nuestra disposición son las siguientes:


Página en blanco: como su propio nombre indica, se muestra una página sin contenido en la que es posible insertar -de forma manual- los componentes (portlets) que se necesiten. Al seleccionar esta opción, escogeremos una disposición de página de entre las disponibles.
Una disposición de página determina cómo se ordenarán los portlets que insertemos en la página, como por ejemplo en una sola columna, a dos columnas (50-50, 30-70,70-30), etcétera.

Panel: una página que permite mostrar cualquier número de portlets en ella, pero únicamente uno a la vez. El usuario seleccionará el portlet a mostrar a través de un menú. El portlet seleccionado ocupará la página entera.

Web insertada: muestra contenido de otra página web dentro de nuestro portal. Un administrador puede establecer una URL desde el menú de configuración de páginas, mostrándose esta en el contexto de nuestro portal.

Enlace a URL: una página que simplemente redirecciona a la URL configurada, ya sea una url de nuestro portal o un enlace a una web externa.

Enlace a página de este sitio: permite seleccionar una página dentro de nuestro sitio a la que la página creada redireccionará al usuario. Puede ser útil, por ejemplo, para ubicar una página que se encuentra en un nivel de profundidad mayor en el menú de navegación del sitio de forma que esté más visible, creando una página que la enlace a un nivel más superior de la estructura.

En cualquier caso, en Liferay es posible crear tipos de página personalizados de acuerdo a necesidades concretas.

12 de julio de 2017

:: PHP. Obtener datos sobre la salida y puesta de sol

Aunque existen algunos servicios para obtener esta información, el lenguaje de programación PHP nos lo pone un poco más fácil, al estar disponible la función:

date_sun_info(fecha, latitud, longitud)

Como prueba de concepto recuperaremos la información sobre salida y puesta de sol para una fecha y ubicación determinada:

<?php $sun_info = date_sun_info(strtotime("now"), 43.4222027, -5.8248455);
foreach ($sun_info as $clave => $valor) {
    echo "$clave: " . date("H:i:s", $valor) . "
";
}
?>

3 de julio de 2017

:: Alfresco. Eliminación del contenido de la papelera

Cuando un usuario elimina -en Alfresco- cualquier contenido, este es movido a la papelera de reciclaje y se mantendrá aquí hasta que el propio usuario o el usuario administrador lo elimine definitivamente.

En cualquier caso, es posible programar la eliminación de estos contenidos cada cierto tiempo. De esta manera, para llevar a cabo esta tarea debemos incluir la siguiente línea en el fichero: "alfresco-global.properties":

trashcan-cleaner.cron=0 30 * * * ?

27 de junio de 2017

:: Liferay. Evitar que caduque la sesión de un usuario

En algunas implantaciones, requieren que la sesión de un usuario no caduque, es decir, que este -una vez iniciada la sesión- permanezca logueado.


Para llevar a cabo esta tarea deberemos  modificar el fichero "portal-ext.properties" estableciendo los siguientes valores.

#Session timeout Value
session.timeout=480
session.timeout.warning=1
session.timeout.auto.extend=true



21 de junio de 2017

:: Alfresco. Importar y descomprimir un fichero .ZIP

A modo de prueba de concepto, una posible opción para importar y descomprimir un archivo .ZIP en Alfresco, sería la siguiente.

En este caso, utilizaremos reglas para descomprimir un fichero .ZIP cargado en Alfresco.

Crearemos una carpeta, por ejemplo "Entrada", sobre la que definiremos una regla de contenido.
Para ello seleccionaremos la opción: "Gestionar reglas" > "Nueva regla"
- Cuando entran o se crean elementos en esta carpeta
- Tipo MIME es ZIP
- Importar a la carpeta seleccionada (por ejemplo "Elementos importados")

Cuando subamos un fichero .ZIP a la carpeta "Entrada", se ejecutará la regla definida, importándose (extrayéndose) los ficheros del .ZIP a la carpeta "Elementos importados"

Para el caso de que el propio .zip tuviera otros .zip, sería necesario definir esta regla para que se aplicara a las subcarpetas, pero en cualquier caso esta es sólo un aprueba de concepto sobre un posible planteamiento para importar y descomprimir ficheros .ZIP de una forma sencilla.

Como es lógico, podemos subir a Alfresco un fichero .zip y una vez subido seleccionar la acción "Descomprimir en...", pero requeriría intervención manual, que no era el objetivo de este post.


14 de junio de 2017

:: Liferay. Probar el envío de correo

Cuando estamos desarrollando es habitual poder probar el envío de notificaciones por correo electrónico en nuestros portlets.


Para ello, podemos hacer uso de la herramienta "fakeSMTP" que podemos descargar en la siguiente url: http://nilhcem.com/FakeSMTP/

Tras instalar el .JAR autoextraible y seleccionar la carpeta donde se almacenarán los correos electrónicos que recibamos, pulsaremos sobre el boton "Start Server".

Iremos a nuestro Liferay y en el panel de control (versión 6.2) seleccionaremos : "Configuración" > "Administración del servidor" > "Correo".
En este punto revisaremos los valores configurados, normalmente, en el puerto 25.


Desde uno de nuestros portlets haremos una prueba de envío, y verificaremos desde nuestro servidor de correo instalado, que efectivamente se ha recibido este correo.



:: Cookies de nuestra página web. ¿Para qué sirve cada una?

A menudo una pregunta que nos hacen es qué cookies se están utilizando en mi página y para qué sirven. Para ver las cookies, podemos selecci...