Categorías: desarrollo sharepoint 2013

[SharePoint] Crear, depurar y pruebas unitarias en TimerJob

Echando la vista atrás hace tiempo que escribo un post de desarrollo 100% así que ya va siendo hora. SharePoint entre sus virtudes es que es una herramienta en la que se pueden hacer muchas cosas de muchas formas diferentes. Una de esas herramientas en la que utilizamos cuando solamente cuando es impepinable es el TimerJob.

¿Que es un TimerJob?

Un TimerJob lo podemos definir como una Tarea programada de Windows que se ejecuta sobre un/unas colecciones de sitio para hacer una determinada acción, en un determinado tiempo y con una cierta frecuencia (cada hora, cada minuto, cada lunes,etc…) dentro de nuestro SharePoint.

¿Qué podemos hacer en un TimerJob?


En un TimerJob podemos hacer prácticamente de todo, pero hay que saber muy bien cuando usarlo, ya que por ejemplo si quiero estar en el campo puedo ir con un Ferrari aunque NO es conveniente verdad :-). Por lo general yo recomiendo usarlo cuando queremos hacer una acción con cierta periodicidad y que no responden a ningún evento que hay en SharePoint. Porque si responde a un evento de SharePoint mejor hacer uso de un Workflows o EventReceiver. Entonces que nos queda pues el sincronizar SharePoint con otros datos externos, enviar información almacenada en SharePoint a otros sistemas, envió de informes con información relativa de SharePoint, etc…

Una vez ya tenemos un caso donde el uso del TimerJob es lo más conveniente vamos a implementarlo ¿Como? para ello aquí este magnifico post del maestro Andrew Connell
En primer lugar nos creamos una clase que herede de Microsoft.SharePoint.Administration.SPJobDefinition y sobre escribimos el método «Execute»

namespace TaskLogger {
public class TaskLoggerJob : SPJobDefinition{
public TaskLoggerJob () : base(){ }
public TaskLoggerJob (string jobName, SPService service, SPServer server, SPJobLockType targetType) :
base (jobName, service, server, targetType) { }
public TaskLoggerJob (string jobName, SPWebApplication webApplication) :
base (jobName, webApplication, null, SPJobLockType.ContentDatabase)
 {
this.Title = "Task Logger";
 }
public override void Execute (Guid contentDbId)
{
// get a reference to the current site collection's content database
SPWebApplication webApplication = this.Parent as SPWebApplication;
SPContentDatabase contentDb = webApplication.ContentDatabases[contentDbId];
SPList taskList = contentDb.Sites[0].RootWeb.Lists["Tasks"];
SPListItem newTask = taskList.Items.Add();
 newTask["Title"] = DateTime.Now.ToString(); newTask.Update();
}
}
}

La funcionalidad de este código es que añade un elemento a la lista «Task».
El siguiente paso es hacer que cuando activemos/desactivemos esta Feature en nuestro Site pues instalemos/desinstalemos este TimerJob para ello podemos hacer uso de este código:

public override void FeatureActivated (SPFeatureReceiverProperties properties)
{
SPSite site = properties.Feature.Parent as SPSite;
 // make sure the job isn't already registered
foreach (SPJobDefinition job in site.WebApplication.JobDefinitions)
{ if (job.Name == TASK_LOGGER_JOB_NAME) job.Delete(); }
 // install the job
TaskLoggerJob taskLoggerJob = new TaskLoggerJob(TASK_LOGGER_JOB_NAME, site.WebApplication);
 SPMinuteSchedule schedule = new SPMinuteSchedule();
schedule.BeginSecond = 0;
schedule.EndSecond = 59;
schedule.Interval = 5;
taskLoggerJob.Schedule = schedule;
taskLoggerJob.Update(); }

public override void FeatureDeactivating (SPFeatureReceiverProperties properties)
 {
SPSite site = properties.Feature.Parent as SPSite;
// delete the job
foreach (SPJobDefinition job in site.WebApplication.JobDefinitions)
 { if (job.Name == TASK_LOGGER_JOB_NAME) job.Delete(); }

Posibles errores

Parece muy bonito todo esto sobre todo si lo ejecutamos en nuestro entorno de desarrollo donde más o menos los dos/tres usuarios que tenemos tiene permisos para todo, el usuario administrador tiene permiso para todo, pero tambien el usuario administrador de la base de datos e incluso el del pool de aplicaciones. Esto puede propiciar errores a la hora de ponerlo en producción hay que tenerlo muy encuentra porque sino no va a funcionar.
El primer error que se nos puede producir es que no se active la característica en nuestro sitio y nos de un error de que no se ha podido activar la feature. Nuestro pensamiento es que por la interfaz gráfica no se puede hacer pues lo hacemos haciendo uso de PowerShell (que como es la moda y me se las instrucciones para activarla lo tengo fácil). Ejecutamos el siguiente comando en la consola PowerShell:
Enable-SPFeature -Identity «Id de la feature» -WebApplication http://myentorno.dev
Y funciona a la perfección. Entonces esperamos que llegue el momento y se ejecute nuestro desarrollo pero miramos la tarea en la Administración Central y vemos que nos ha dado un error «Object not found». Vale el primer pensamiento es decir algo que me he desarrollado muy mal, pero no existe un problema ya que el usuario con el que se ejecuta este proceso es el usuario del Pool de Aplicaciones de la Adminsitración Central. Con esto quiero indicar que hay que mirar todas las variables que hay en el entorno y darnos cuenta de que nuestro desarrollo va a funcionar en el sitio de producción. No es lo mismo un desarrollo para un colección de sitios que un desarrollo para la Administración Central. El no tener en cuenta estas variables a la hora de diseñar una solución nos puede costar mucho tiempo perdido una vez ya tenemos montada la solución.

Depurar el Timer Job

La verdad es que la depuración es algo muy importante y que gracias a una herramienta tan completa como es Visual Studio nos lo pone de una forma relativemente simple. Para ello lo único que tenemos que hacer es Asociar el proceso OWSTIMER desde Visual Studio para ello Depurar->Asociar Proceso

A continuación seleccionamos el proceso OWSTIMER y a depurar 🙂

Como hacer Pruebas Unitarias

Bueno lo primero es que yo creo que en todos los proyectos tenemos que hacer pruebas unitarias independientemente del contexto, que mi función como constructor de aplicaciones web es hacerlas con la mayor calidad posible (dentro de mis conocimientos) y para ello creo que un buen ciclo de vida del produce da un plus de calidad a nuestros desarrollos que para algo somos ingenieros de software para hacer calidad en lo que hacemos sino mejor hacer churros 😛 Dicho esto os aconsejo a todos que no os perdáis la charla sobre esta materia que va a impartir David Martos en la Iberian SharePoint Conference (Aun no estas inscrito? A que esperás?).
Las pruebas unitarias nos brindan la facilidad de probar una unidad de código con el objetivo de llevar acabo una prueba de forma rápida, simple y siempre con el mismo resultado sin importar el número de veces que vaya a ser ejecutado.
Hace ya un tiempo que hice una pequeña introducción a la pruebas unitarias en este post. El cual es valido al 100 % el crearlas dentro de un proyecto de TimerJob pero que ventajas extra nos da el hacer pruebas unitarias en un TimerJob. La principal ventaja es que no tenemos que esperar a que se ejecute el proceso nos simplifica mucho las pruebas, la depuración del mismo. Una vez a superado las pruebas unitarias estaremos seguro que nuestro desarrollo funciona a la perfección. Ahora nos quedará quedarnos con la parte de sistemas y ver si disponemos de los permisos necesarios para que nuestro TimerJob funcione a la perfección.

Compartir
Publicado por
Adrián Díaz

Este sitio web utiliza cookies para que tengas la mejor experiencia de usuario. Si continuas navegando, estás dando tu consentimiento para aceptar las cookies y también nuestra política de cookies (esperemos que no te empaches con tanta cookie 😊)