in

DotNetSide

Dot Net South Italy Developers User Group

Articoli

Articoli pubblicati dagli iscritti a .netSide

Tutorial su Notification services - Seconda parte

articolo di Giuseppe Di Cillo  

L’applicazione di notifica

Dopo aver analizzato nella prima parte di questo tutorial un pò di concetti teorici, passiamo ad analizzare l'applicazione di notifica. Tutto si basa su eventi, subscribers, subscriptions, notifiche. Andiamo ad esaminare più in dettaglio questi elementi.

NOTA: In questo tutorial si semplifica al massimo la struttura di tutta l’applicazione di notifica, perché scopo non è quello di elencare tutte le tabelle, views, stored procedures, triggers, campi, di Notification Services, ma di chiarirne i principi di funzionamento.

Eventi

L’applicazione dovrà raccogliere gli eventi (sotto forma di dati), li confronterà con le subscriptions, e, se corrisponderanno, invierà le relative notifiche ai subscribers.
Come detto precedentemente, nel nostro esempio, i subscribers devono poter essere notificati quando la quantità disponibile di un certo prodotto sale sopra una determinata soglia. La soglia non sarà fissa, ma sarà scelta da ogni subscribers. Quindi, prima di tutto, si dovranno definire in forma tabellare i dati relativi agli eventi che vogliamo monitorare.
Nel nostro caso, la tabella degli eventi, conterrà i dati riguardanti le modifiche dei valori delle giacenze di magazzino di prodotti.

La parte dell’applicazione di notifica preposta a inserire dati in questa tabella, viene chiamata “Event Provider”. I provider sono di due tipi: “Non hosted” e “Hosted”.

Providers Non Hosted

Con i provider “Non hosted” dovremo essere noi sviluppatori a decidere quando e come inserire gli eventi nel database dell’applicazione di notifica.
Potremo fare questo tramite delle API dei seguenti tipi:

• .NET
• COM
• XML
• SQL

Nel nostro tutorial useremo le stored procedures SQL messe a disposizione da Notification Services lanciandole da uno script sql. In uno scenario reale dovremmo inserire tale codice in un trigger nel database della nostra applicazione, oppure potremmo integrare del codice .NET nella nostra applicazione di e-commerce per inserire gli eventi nel database dell’applicazione di notifica ogni qualvolta qualcuno, tramite l’interfaccia web, effettua una modifica sulla giacenza di magazzino.

Providers Hosted

Mentre i providers “Non hosted” vengono gestiti direttamente dallo sviluppatore, quelli “Hosted” vengono eseguiti all’interno dell’istanza di Notification Services. Potrebbero quindi essere dei providers che, per esempio, tengono sotto controllo a schedulazioni predefinite, i dati della tabella delle giacenze di magazzino, per controllare se sono state modificate. Notification Services fornisce tre Hosted Providers pronti:

• FileSystemWatcherProvider (tiene sotto controllo una cartella, nella quale lo sviluppatore andrà a salvare dei documenti XML che rappresentano gli eventi da generare)
• SQLProvider (esegue una query a determinati intervalli di tempo, per monitorare le tabelle che ci interessano)
• AnalysisServicesProvider (come il SqlProvider ma prende i dati da cubi OLAP)

Oltre a questi providers predefiniti, lo sviluppatore ne può creare di personalizzati.

Subscribers

La tabella dei Subscribers servirà per memorizzare i dati degli utenti che vogliono ricevere delle notifiche.

NOTA
: Anche se per semplicità nella figura 2 ho raffigurato tale tabella nel database dell’applicazione di notifica, nella realtà è memorizzata nel database di istanza.

In realtà qui non ci sono molto informazioni, infatti tale tabella serve solo per collegarne altre, come ad esempio quella dei “Devices”.

Ogni subscribers può avere associato, tramite questa tabella, uno o più dispositivi di notifica: per esempio un utente potrebbe volere la notifica via email ma anche via SMS. Quindi per ogni record in tabella, specifichiamo l’id del subscriber associato, il nome del dispositivo, l’indirizzo per il dispositivo (indirizzo email per l’smtp, numero di cellulare per gli SMS, etc.), e il nome del DeliveryChannell attraverso il quale le notifiche saranno inviate. Nel nostro tutorial, usiamo EmailChannell, che, naturalmente, è quello che abbiamo definito precedentemente nel file ICF.

Subscriptions

La tabella delle subscriptions specificherà i criteri per far partire le notifiche ai vari subscribers. Nel nostro esempio per ogni subscriber indicheremo il prodotto a cui è interessato il subscriber e la soglia sopra la quale la giacenza del prodotto deve salire affinchè inneschi la notifica. Inoltre possiamo specifcare la localizzazione del messaggio tramite il campo SubscriberLocale, e il dispositivo, scelto tra quelli associati al subscriber, al quale inviare la notifica.

Notifiche

La tabella delle notifiche conterrà i dati che dovranno essere spediti ai subscribers, nonché a quale dispositivo verrà inviato, e con quale localizzazione.

In Notification Services il componente chiamato Generator crea le notifiche, recuperando i dati degli eventi, e confrontandoli con le subscriptions. Questa “generazione” verrà implementata tramite l’esecuzione di una normale INSERT che va a creare i records per la tabella delle notifiche.
Per esempio, possiamo immaginare una INSERT…SELECT come questa:

INSERT INTO Notifiche(SubscriberId, ProductId, UnitsInStock)
SELECT sottoscrizioni.SubscriberId, eventi.ProductId, eventi.UnitsInStock
FROM Eventi INNER JOIN sottoscrizioni
ON eventi.ProductId = sottoscrizioni.ProductId
WHERE eventi.UnitsInStock >= sottoscrizioni.QtyThreshold

Più avanti vedremo che il comando reale sarà un po’ più complesso, ma qui si è voluto semplificare al massimo per chiarire come per ogni notifica da gestire, avremo bisogno di realizzare un comando sql di questo tipo. Tale comando verrà eseguito dal componente di Notification Services chiamato Generator.

Le notifiche, naturalmente saranno formattate in base al file xslt chiamato “Formattazione.xslt”, di cui mostriamo qui il codice:

<?xml version="1.0" encoding="UTF-8" ?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

  <xsl:template match="notifications">
    <html>
      <body>
        <xsl:apply-templates/>
        <i>Notification Services Test.</i>
      </body>
    </html>
  </xsl:template>

  <xsl:template match="notification">
    Il numero dei pezzi in magazzino del prodotto  <b>
      <xsl:value-of select="ProductId" />-<xsl:value-of select="ProductName" />
    </b> <br/>
    ha superato la soglia di <b>
      <xsl:value-of select="QtyThreshold" />
    </b><br/>
    <br/>
  </xsl:template>
</xsl:stylesheet>

Applicazione di notifica

In definitiva per la nostra applicazione di notifica, dovremo definire :

• La struttura dei dati di Eventi, Subscriptions, e Notifiche
• Il comando sql per mettere assieme i dati di eventi e subscriptions in modo da generare le notifiche.
• La configurazione di Event Providers (per la raccolta degli eventi), Generators (che confrontano sottoscrizioni ed eventi per creare le notifiche) e Distributors (che si occupano di inviare le notifiche).

Tutto ciò verrà definito tramite un file XML chiamato ADF (Application Definition File).

Andiamo quindi a esaminare, uno per volta, i singoli elementi che formano il file ADF. All’interno del file zip trovate l’intero file xml, chiamato “AvvisoMagazzinoADF.xml”.

La struttura del file ADF

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

  <Application xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.microsoft.com/MicrosoftNotificationServices/ApplicationDefinitionFileSchema">

 

L’elemento radice che definisce lo schema XSD per il file. Lo lasciamo così com’è.

 

<EventClasses>

<EventClass>

<EventClassName>GiacenzaModificata</EventClassName>

<Schema>

<Field>

<FieldName>ProductId</FieldName>

<FieldType>int</FieldType>

<FieldTypeMods>not null</FieldTypeMods>

</Field>

<Field>

<FieldName>ProductName</FieldName>

<FieldType>nvarchar(1000)</FieldType>

<FieldTypeMods>not null</FieldTypeMods>

</Field>

<Field>

<FieldName>UnitsInStock</FieldName>

<FieldType>int</FieldType>

<FieldTypeMods>not null</FieldTypeMods>

</Field>

</Schema>

</EventClass>

</EventClasses>

 

L’elemento EventClass serve a specificare la struttura della tabella che conterrà i dati degli eventi. Tale tabella si chiamerà

GiacenzaModificata,come indicato nell’elemento EventClassName. Come specificato prima nell’articolo, la nostra tabella degli

eventi dovrà contenere i campi ProductId e UnitsInStock. Per semplificare l’applicazione ho preferito aggiungere anche il campo

ProductName. Tali campi vengono specificati tramite i sottoelementi Field.

 

<SubscriptionClasses>

   <SubscriptionClass>

 <SubscriptionClassName>SottoscrizioneGiacenza</SubscriptionClassName>

   <Schema>

   <Field>

  <FieldName>DeviceName</FieldName>

  <FieldType>nvarchar(255)</FieldType>

  <FieldTypeMods>not null</FieldTypeMods>

  </Field>

   <Field>

  <FieldName>SubscriberLocale</FieldName>

  <FieldType>nvarchar(10)</FieldType>

  <FieldTypeMods>not null</FieldTypeMods>

  </Field>

   <Field>

  <FieldName>ProductId</FieldName>

  <FieldType>int</FieldType>

  <FieldTypeMods>not null</FieldTypeMods>

  </Field>

   <Field>

  <FieldName>QtyThreshold</FieldName>

  <FieldType>int</FieldType>

  <FieldTypeMods>not null</FieldTypeMods>

  </Field>

  </Schema>

   <EventRules>

   <EventRule>

  <RuleName>GiacenzaModificataRegola</RuleName>

  <EventClassName>GiacenzaModificata</EventClassName>

  <Action>INSERT INTO AvvisoGiacenzaModificata(SubscriberId, DeviceName, SubscriberLocale, ProductId, ProductName, UnitsInStock, QtyThreshold) SELECT sottoscrizioni.SubscriberId, sottoscrizioni.DeviceName, sottoscrizioni.SubscriberLocale, eventi.ProductId, eventi.ProductName, eventi.UnitsInStock, sottoscrizioni.QtyThreshold FROM GiacenzaModificata AS eventi INNER JOIN SottoscrizioneGiacenza AS sottoscrizioni ON eventi.ProductId = sottoscrizioni.ProductId WHERE eventi.UnitsInStock >= sottoscrizioni.QtyThreshold;</Action>

  </EventRule>

  </EventRules>

  </SubscriptionClass>

  </SubscriptionClasses>


Con l’elemento SubscriptionClass possiamo definire la tabella delle sottoscrizioni, e nel nostro esempio, tale tabella, si chiamerà “SottoscrizioneGiacenza”, come indicato dal sottoelemento “SubscriptionClassName”. E’ da notare che Notification Services aggiungerà alla tabella di Subscriptions anche il campo SubscriberID, anche se non definito direttamente. Per poter aggiungere sottoscrizioni, dovremo crearle da codice. Inoltre qui, grazie al sottoelemento EventRule, possiamo specificare il criterio di Matching tra sottoscrizioni ed eventi. Tale criterio viene definito nel sottoelemento Action, come una INSERT SELECT che andrà ad aggiungere alla tabella definita dall’elemento NotificationClass, i dati relativi alle notifiche. Il sottoelemento <EventClassName> specifica il nome dell’EventClass che innesca tale Azione che, naturalmente, nel nostro esempio è GiacenzaModificata che abbiamo definito precedentemente nell’elemento EventClass.

<NotificationClass>

 <NotificationClassName>AvvisoGiacenzaModificata</NotificationClassName>

  <Schema>

  <Fields>

  <Field>

  <FieldName>ProductId</FieldName>

  <FieldType>int</FieldType>

  </Field>

  <Field>

  <FieldName>ProductName</FieldName>

  <FieldType>nvarchar(1000)</FieldType>

  </Field>

  <Field>

  <FieldName>UnitsInStock</FieldName>

  <FieldType>int</FieldType>

  </Field>

  <Field>

  <FieldName>QtyThreshold</FieldName>

  <FieldType>int</FieldType>

  </Field>

  </Fields>

  </Schema>

  <ContentFormatter>

  <ClassName>XsltFormatter</ClassName>

  <Arguments>

 <Argument>

  <Name>XsltBaseDirectoryPath</Name>

  <Value>%_PercorsoApp_%</Value>

  </Argument>

  <Argument>

  <Name>XsltFileName</Name>

  <Value>Formattazione.xslt</Value>

  </Argument>

  </Arguments>

  </ContentFormatter>

  <Protocols>

  <Protocol>

  <ProtocolName>SMTP</ProtocolName>

   <Fields>

   <Field>

  <FieldName>Subject</FieldName>

  <SqlExpression>'Prodotto in magazzino: '</SqlExpression>

  </Field>

   <Field>

  <FieldName>BodyFormat</FieldName>

  <SqlExpression>'html'</SqlExpression>

  </Field>

   <Field>

  <FieldName>From</FieldName>

  <SqlExpression>'dicillo@gmail.com'</SqlExpression>

  </Field>

  <Field>

  <FieldName>Priority</FieldName>

  <SqlExpression>'Normal'</SqlExpression>

  </Field>

   <Field>

  <FieldName>To</FieldName>

  <SqlExpression>DeviceAddress</SqlExpression>

  </Field>

  </Fields>

  </Protocol>

  </Protocols>

  </NotificationClass>

  </NotificationClasses>

 

L’elemento NotificationClass serve, tra le altre cose, per definire, tramite l’elemento Schema con i sottoelementi Field, la struttura della tabella che conterrà i dati delle notifiche da inviare. Tali dati saranno inseriti dalla INSERT SELECT specificata precedentemente nel sottoelemento EventRule di SubscriptionClass. Il sottoelemento ContentFormatter fa riferimento a un file xslt, che nel file zip trovate già pronto, per la formattazione della notifica, mentre Protocols indica il protocollo di invio e indica vari parametri necessari al suo corretto funzionamento. I valori tra segni percentuale sono parametri i cui valori sono stati passati dall’ICF nell’elemento application.
Alla tabella di notificationclass, oltre alle colonne specificate, NS aggiunge le 3 seguenti colonne:

• SubscriberID
• DeviceName
• SubscriberLocale

<Providers>

  <NonHostedProvider>

  <ProviderName>GenerazioneEventiTSQL</ProviderName>

  </NonHostedProvider>

  </Providers>

i providers, come spiegato in precedenza, sono i componenti che si occuperanno di raccogliere i dati degli eventi. Nel nostro esempio inseriremo gli eventi tramite delle istruzioni t-sql che inseriranno nella tabella degli eventi i dati che servono, e per questo possiamo definire il provider come NonHosted e con un nome qualsiasi.

  <Generator>

  <SystemName>%_NomeServerApp_%</SystemName>

  </Generator>

L’elemento generator rappresenta su quale macchina notification services deve svolgere l’attività di generazione delle notifiche. _NomeServerApp_ è il nome di una variabile specificata nel file ICF attraverso il quale è stato passato il nome del server.

<Distributors>

  <Distributor>

  <SystemName>%_NomeServerApp_%</SystemName>

  <QuantumDuration>PT15S</QuantumDuration>

  </Distributor>

  </Distributors>

L’elemento distributor serve a specificare quale macchina si occuperà di prendere i dati delle notifiche, formattarli, e indirizzarli verso i sistemi che si occuperanno dell’invio. Con QuantumDuration si specifica un intervallo di tempo per l’invio automatico delle notifiche (in questo caso, ogni 15 secondi).

NOTA: nella versione standard gli event providers, i generator e i distributor devono essere tutti sullo stesso server. Nella versione Enterprise, invece, potremo specificare server diversi in modo da suddividere il carico di lavoro.

<ApplicationExecutionSettings>

<QuantumDuration>PT15S</QuantumDuration>

</ApplicationExecutionSettings>

 

Tale elemento serve a specificare diverse impostazioni dell’applicazione di notifica. Nel nostro esempio, indichiamo solo l’intervallo di tempo per la generazione delle notifiche (15 secondi).

Nella prossima e ultima parte di questo tutorial verrà inizializzata l’istanza di Notification Services e l’applicazione di notifica, tramite il Management Studio.

Only published comments... Mar 16 2007, 10:42 PM by DotNetSide Staff
Filed under:
Powered by Community Server (Commercial Edition), by Telligent Systems