aspektisuuntautunut€ohjelmointi€€ja … ·...

73
ASPEKTISUUNTAUTUNUT OHJELMOINTI JA OHJELMISTON MODULARISOINTI Juhani Sannikka Erikoistyö Tietojenkäsittelytiede Kuopion yliopiston tietojenkäsittelytieteen laitos Maaliskuu 2005

Upload: others

Post on 16-Jul-2020

1 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: ASPEKTISUUNTAUTUNUT€OHJELMOINTI€€JA … · Luvussa€1€esitellään€aspektisuuntautuneen€ohjelmointitavan€historiaa€ja€käsitteistöä. Luvussa€2€esitellään€AspectJkieli,€joka€toteuttaa€aspektisuuntautuneen€ohjelmoinnin

ASPEKTISUUNTAUTUNUT OHJELMOINTI  JA

OHJELMISTON MODULARISOINTI

Juhani SannikkaErikoistyöTietojenkäsittelytiedeKuopion yliopistontietojenkäsittelytieteen laitosMaaliskuu 2005

Page 2: ASPEKTISUUNTAUTUNUT€OHJELMOINTI€€JA … · Luvussa€1€esitellään€aspektisuuntautuneen€ohjelmointitavan€historiaa€ja€käsitteistöä. Luvussa€2€esitellään€AspectJkieli,€joka€toteuttaa€aspektisuuntautuneen€ohjelmoinnin

KUOPION YLIOPISTO, informaatioteknologian ja kauppatieteiden tiedekuntaTietojenkäsittelytieteen koulutusohjelma

JUHANI SANNIKKA, Aspektisuuntautunut ohjelmointi ja ohjelmiston modularisoin­tiErikoistyö, 73 s., 12 liitettä (62 s.)Erikoistyön ohjaaja: FM Harri KarhunenErikoistyön tarkastaja: FM Heli LintulaHuhtikuu 2005

Avainsanat: aspectj, modularisointi, autentikointi, auktorointi, transaktio

AspectJ­ohjelmointikieli on Java­kielen laajennos,  joka tarjoaa myös aspektisuuntau­tuneen  ohjelmoinnin  työkalun.  Se  sisältää  AspectJ­kääntäjän,  jonka  tuottamaa  tavu­koodia  tavallinen  Javan  virtuaalikone  ymmärtää.  Aspektien  koodauksessa  käytetäänhyväksi luokissa toteutettua perustoiminnallisuutta.Join point tarkoittaa luokissa toteutettua ohjelman kohtaa, kuten metodia, konstrukto­ria tai ohjelman kontrollivirtaa,  jossa niitä suoritetaan. Pointcut on aspektissa esiteltyja määritelty ohjelmalohko, joka sieppaa halutut ohjelman join point –kohdat suoritet­tavaksi.  Sieppaaminen  voi  perustua  luokan  tai  metodin  nimeen  tai  tyyppiin.  Niidenkuvaamiseen voidaan käyttää reflektointia. Pointcut –lohkojen valitsemien join point ­kohtien suorituksia voidaan ohjeistaa advice­määrittelyillä. Advice­lohkon koodi täy­dentää  join  point  ­kohtien  toimintoja.  Advice­lohkon  koodi  voidaan  suorittaa  niitäennen, niiden jälkeen tai se voi korvata alkuperäisen toiminnon kokonaan.AspectJ­ohjelmointikieli  on  aspektisuuntautunut  ohjelmointikieli,  joka  mahdollistaaluokkien  toiminnallisuuden  koostamisen  ja  käsittelemisen  kokonaisuuksina,  jotkamuodostavat  ohjelman  kannalta  poikkileikkauksellisia  tehtäviä  tai  ominaisuuksia.Pelkkänä  luokkatoteutuksena näiden tehtävien koodi on vaikeasti hallittavissa, koskase  levittäytyy  laajalle  ohjelmistoelementtien  koodin  sekaan.  Aspekti  auttaa  poikki­leikkauksellisten  tehtävien  modularisoinnissa,  jolloin  ohjelman  rakenne  selkiytyy.Ohjelmiston  perustoiminnallisuus  on  paremmin  hallittavissa  ja  myös  muutokset  as­pektien muodostamaan modulaariseen rakenteeseen on helpompi toteuttaa, kuin luok­kiin  levitetyn koodin muutokset. Aspekteja voidaan määritellä myös ohjaamaan  oh­jelmistokehityksen koodaustapoa. Tällaiset aspektit saavat kääntäjän tulostamaan va­roituksia tai estämään väärän koodauksen.Tässä  raportissa  kerrotaan  aspektisuuntautuneen  ohjelmoinnin  keinoista  toteuttaapoikkileikkauksellisten tehtävien, kuten autentikointi, auktorisointi  ja transaktiot mo­dulaarisina uudelleen käytettävinä ratkaisuina. Raportissa kerrotaan myös ratkaisuissakäytettävistä suunnittelumalleista.Luvussa  1  esitellään  aspektisuuntautuneen ohjelmointitavan  historiaa  ja  käsitteistöä.Luvussa 2 esitellään AspectJ­kieli,  joka toteuttaa aspektisuuntautuneen ohjelmoinninympäristön.  Luvussa  3  käsitellään  esimerkkejä  suunnittelumallien  toteuttamiseksiaspekteina ja  luvussa 4 säikeiden käsittelyä modulaarisesti aspektien avulla. Luvussa5  käsitellään  järjestelmän  autentikoinnin  ja  auktorisoinnin  modulaarisia  ratkaisuja.Luvussa  6  esitetään  erilaisia  aspektisuuntautuneen  ohjelmoinnin  mahdollisuuksiatransaktion modulaariseen  toteutukseen. Lukujen 3­6 esimerkit perustuvat AspecJ inAction –teokseen, jonka on kirjoittanut R. Laddad.

Page 3: ASPEKTISUUNTAUTUNUT€OHJELMOINTI€€JA … · Luvussa€1€esitellään€aspektisuuntautuneen€ohjelmointitavan€historiaa€ja€käsitteistöä. Luvussa€2€esitellään€AspectJkieli,€joka€toteuttaa€aspektisuuntautuneen€ohjelmoinnin

3

Sisällysluettelo

1  ASPECT ORIENTED PROGRAMMING............................................................. 51.1  Oliosuuntautuneisuuden ohjelmoinnin kehittyminen...................................... 51.2  AOP­tekniikan tavoitteet ............................................................................... 61.3  Näkymien muodostaminen ja sovelluksen ominaisuudet................................ 81.4  AOP:n vaikutus modularisointiin................................................................... 91.5  AOP­kielinen implementointi ...................................................................... 12

2  ASPECTJ............................................................................................................ 152.1  Join point..................................................................................................... 152.2  Pointcut ....................................................................................................... 172.3  Advice......................................................................................................... 19

3  SUUNNITTELUMALLIT .................................................................................. 223.1  Worker­objektin luonti ­ suunnittelumalli .................................................... 22

3.1.1  Worker­metodin palauttama arvo ......................................................... 24

3.1.2  Worker­objektin kontekstin hallinta ..................................................... 25

3.2  Madonreikä suunnittelumalli ....................................................................... 26

3.2.1  Madonreikä suunnittelumallin periaate................................................. 26

3.2.2  Madonreikämallin kaava...................................................................... 27

3.3  Poikkeuksien käsittely ................................................................................. 30

3.3.1  Tehtäväkohtaisen poikkeuksen käsittely aspektissa .............................. 31

3.3.2  Liiketoimintokohtaisen poikkeuksen käsittely aspektissa ..................... 32

3.3.3  Poikkeuksen taltiointi aspektissa .......................................................... 32

3.4  Osallistuja­suunnittelumalli ......................................................................... 33

3.4.1  Osallistuja­suunnittelumallin kaava...................................................... 36

4  SÄIETURVALLISUUS...................................................................................... 38

4.1  Swing ja yhden säikeen sääntö..................................................................... 38

4.1.1  Perinteinen ratkaisu.............................................................................. 39

4.1.2  Säieturvallisuus aspektina .................................................................... 41

Page 4: ASPEKTISUUNTAUTUNUT€OHJELMOINTI€€JA … · Luvussa€1€esitellään€aspektisuuntautuneen€ohjelmointitavan€historiaa€ja€käsitteistöä. Luvussa€2€esitellään€AspectJkieli,€joka€toteuttaa€aspektisuuntautuneen€ohjelmoinnin

4

4.1.3  Objektin lukitusmalli aspektina............................................................ 43

5  AUTENTIKOINTI JA AUKTORISOINTI.......................................................... 46

5.1  Pankkijärjestelmä ........................................................................................ 465.2  JAAS­pohjainen autentikointi perinteisellä tavalla ....................................... 48

5.2.1  LoginContext –objektin luonti ............................................................. 48

5.2.2  Takaisinkutsun käsittelijä..................................................................... 49

5.2.3  Kirjautumisen konfiguraatiotiedosto .................................................... 49

5.3  Autentikointi AspectJ­ratkaisuna ................................................................. 505.4  Auktorisointi ............................................................................................... 52

5.4.1  JAAS­pohjainen auktorisointi luokkatoteutuksena ............................... 52

5.4.2  JAAS­pohjainen auktorisointi AspectJ­toteutuksena ............................ 53

6  TRANSAKTIO................................................................................................... 55

6.1  Ydin tehtävien toteutus................................................................................ 556.2  Transaktion perinteinen ratkaisu .................................................................. 566.3  AspectJ­kielinen transaktion ratkaisu........................................................... 59

6.3.1  JDBCTransactionAspect­aspektin koodin selitys ................................. 61

6.3.2  BankingTransactionAspect­aspektin koodin selitys.............................. 63

6.4  Yksi transaktio – useita alijärjestelmiä ......................................................... 63

6.4.1  TransactionParticipantAspect­aspektin selitys...................................... 64

6.4.2  Usean alijärjestelmän transaktion toteuttava perusaspekti..................... 67

6.4.3  Muutetun JDBCTransactionAspect­aspektin koodin selitys ................. 68

6.5  JTA­pohjainen transaktion hallinta .............................................................. 697  YHTEENVETO.................................................................................................. 71

LÄHTEET.................................................................................................................. 72

Page 5: ASPEKTISUUNTAUTUNUT€OHJELMOINTI€€JA … · Luvussa€1€esitellään€aspektisuuntautuneen€ohjelmointitavan€historiaa€ja€käsitteistöä. Luvussa€2€esitellään€AspectJkieli,€joka€toteuttaa€aspektisuuntautuneen€ohjelmoinnin

5

1 ASPECT ORIENTED PROGRAMMING

1.1 Oliosuuntautuneisuuden ohjelmoinnin kehittyminen

Tietojenkäsittelyjärjestelmät  ja  ohjelmointikielet  ovat  kehittyneet konekielistä  (assem­

bly)  käsitteiden  ja  kaavojen  muodostamiseen  ja  kääntämiseen,  proseduurien,  rakentei­

den,  toimintojen,  logiikan  ohjelmointiin  ja  abstraktien  tietotyyppien  käyttöön.  Tämä

ohjelmointitekniikan  kehitys  on  parantanut  mahdollisuuksia  käsitellä  lähdekoodissa

erillisiä tehtäväkonaisuuksia (concerns).

Nykyisin  vallitsevassa  oliosuuntautuneessa  ohjelmoinnissa  (OOP,  Object  Oriented

Programming) ohjelman käsitteet ja toiminnot on ratkaistu olioiden ja niiden toimintoja

ohjaavan koodin avulla. Olioiden käyttäytyminen  ja data muodostavat abstrahoidut (ja

fyysiset)  käsitteet  ohjelman  suorituksessa.  Olio­ohjelmoinnilla  pysytään  ratkaisemaan

hyvin  monimutkaisia  ongelma­alueita,  mutta  silläkin  on  eräitä  rajoitteita.  Esimerkiksi

joitakin ohjelman suorituksessa vaadittuja toimintoja ei voida koodata yhden ohjelman

osan  suoritettavaksi,  vaikka  ne  sille  luontevasti  kuuluisivatkin.  OO­teknologiassa  on

huomioitava globaaleja  rajoitteita  (constraints)  ja kaikkialla  yleisesti vaikuttavaa  (pan­

demic) käyttäytymistä, joita on vaikeaa hallita paikallisesti. Tämä voi vaikeuttaa ongel­

ma  alueiden  eriyttämistä  ja  edellyttää  käyttökohteen  toiminnan  alan  mukaista  sovelta­

mista (domain­specific).

Post­object programming (POP) on olio­ohjelmoinnin seuraava kehitysvaihe,  joka  laa­

jentaa  sen  ilmaisu kykyä.  POP  on  edesauttanut  esimerkiksi  seuraavien  alojen  kehitty­

mistä:

­ toiminnan alan erityiskielet (domain­specific language),

­ generatiivinen eli muodostava ohjelmointi (generative programming),

­ geneerinen eli yleistävä ohjelmointi (generic programming),

­ sääntöjä ja rajoitteita käyttävät sääntökielet (constraint languages),

Page 6: ASPEKTISUUNTAUTUNUT€OHJELMOINTI€€JA … · Luvussa€1€esitellään€aspektisuuntautuneen€ohjelmointitavan€historiaa€ja€käsitteistöä. Luvussa€2€esitellään€AspectJkieli,€joka€toteuttaa€aspektisuuntautuneen€ohjelmoinnin

6

­ luokkien peilaus (reflection) ja meta­ohjelmointi (metaprogramming) ,

­ ominaisuus­suuntautuneiden ohjelmistojen kehittäminen (feature­oriented deve­

lopment),

­ näkymät ja näkökulmat (views, viewpoints), sekä

­ epäsynkroninen viestin välitys (asynchronous message brokering).

Seuraavassa  luvussa  kerrotaan  AOP:sta  (Aspect­Oriented  Programming),  joka  on  eräs

POP­teknologia. AOP tekniikka parantaa ohjelmistojen toteutuksen hallittavuutta, koska

ohjelmiston eri kokonaisvaatimuksia tai ­huolenaiheita (concerns) määritellään erillisinä

ohjelman  osina.  Näille  osille  määritellään  kuvauksia  niiden  yhteyksistä  (relationship),

joiden mukaisesti ohjelman osia koostetaan (weave) yhdeksi kokonaisuutena toimivaksi

sovellukseksi.

1.2 AOP­tekniikan tavoitteet

Ohjelman toiminnot (concerns) voivat huolehtia tehtävistä, jotka muodostuvat käsitteis­

töltään laajoista päättelysäännöistä (high­lewel notions), kuten ohjelmiston turvallisuut­

ta  ja  laatua  palvelevat  tehtävät,  tai  ne  voivat  huolehtia  myös  pienemmistä  tehtävistä

(low­lewel notions), kuten ajureista  ja puskuroinnista. Ohjelman osilla voi olla toimin­

nallisia  piirteitä,  esimerkiksi  ne  voivat  toteuttaa  liiketoiminnallisia  palveluja  (business

rules). Ohjelman osilla voi olla myös ei­toiminnallisia piirteitä, jotka ohjaavat järjestel­

mää, kuten synkronointi  ja transaktioiden hallinta. Vertauksellisesti voidaan sanoa, että

kun OOP pyrkii hyödyntämään  luokkien yhteyttä ja perintäpuuta, AOP pyrkii toteutta­

maan ohjelman toiminnot erillisistä primääri­luokkaisista (first­class) elementeistä,  jot­

ka käynnistyvät suoraan horisontaalisesta oliorakenteesta.

Rakenteellisesti  jotkin  tietojärjestelmän  toiminnot  voidaan  toteuttaa  kätevästi  yhdessä

rakenneosassa,  kun  taas  joidenkin  toimintojen    toteutus  levittäytyy  monelle  rakenne­

Page 7: ASPEKTISUUNTAUTUNUT€OHJELMOINTI€€JA … · Luvussa€1€esitellään€aspektisuuntautuneen€ohjelmointitavan€historiaa€ja€käsitteistöä. Luvussa€2€esitellään€AspectJkieli,€joka€toteuttaa€aspektisuuntautuneen€ohjelmoinnin

7

osalle. AOP keskittäytyy mekanismeihin,  joilla näitä eri rakenneosille  levittäytyviä toi­

mintoja  voidaan  yksinkertaistaa.  AOP:n  päämääränä  on  modularisoida    toteutettavien

ohjelmistojen rakenne, jolloin pienen muutoksen tekeminen loogisella tasolla ei aiheuta

koodin tai suunnittelun tasolla muutoksia moniin eri paikkoihin ohjelmistossa [ElF01].

Ohjelmiston näkymävaatimukset  (aspectual  requirements)  ovat  ongelma­alueita  (con­

cerns),  joita  voidaan  ratkaista  levittämällä  toteutus  osissa  usealle  rakenneosalle.  Esi­

merkkejä tällaisista ongelma­alueista ovat:

­ Synkronointimenetelmät,  jotka  vaativat  melkoisen  joukon  operaatioita  varmis­

tamaan yhdenmukaisen lukitusprotokollan,

­ Monimutkaisten oliograafien läpikäynti, johon tarvitaan globaalia informaatiota.

­ Laskutus mekanismit, joilla hallitaan veloituksia.

­ Vikasietoiset mekanismit, jotka luovat toistuvasti yhdenmukaisia kopioita.

­ Sekä  palvelun  laatua  varmistavat  toiminnot,  jotka  vaativat  järjestelmän  priori­

teettien määrittelyä, kuten autentikointi, jonot ja käyttöoikeudet.

Nämä edellä luetellut toiminnot on perinteisesti toteutettu aliohjelmilla, eikä AOP:kään

hylkää tätä ratkaisua täysin. Perinteisessä toteutuksessa poikkileikkauksellista toimintoa

käsittelevän aliohjelman koodista tulee suttuista ja vaikeasti hallittavaa, kun sitä joudu­

taan toteuttamaan useiden ohjelmistoelementtien koodin seassa. Tämän ongelman kor­

jaamiseksi AOP  tarjoaa aspektin. Se on  mekanismi,  joka kätkee alirutiinit  ja perinnän

sekä  paikallistaa  käsiteltävän  toiminnon  koodin  ohjelmiston  useista  eri  osa­alueista.

AOP ­kehitysympäristö  sisältää punontamekanismin  (weaver),    joka punoo aspektit  ja

sovelluksen peruskoodin koossa pysyväksi järjestelmäksi.

AOP­kehitysympäristö  sisältää  sisäisen  (implisiittisen)  kutsumekanismin,  joten  lähde­

koodin toteuttajan kanssa ei tarvita yhteistyötä, jotta tiedetään kuinka lähdekoodia voi­

daan  kutsua,  kuten  aliohjelmia  käytettäessä.  Kun  erilaisia  toimintoja  voidaan  eriyttää

muusta  ohjelmiston  kehittämisestä,  voidaan  yksinkertaistaa  ja  nopeuttaa  järjestelmän

Page 8: ASPEKTISUUNTAUTUNUT€OHJELMOINTI€€JA … · Luvussa€1€esitellään€aspektisuuntautuneen€ohjelmointitavan€historiaa€ja€käsitteistöä. Luvussa€2€esitellään€AspectJkieli,€joka€toteuttaa€aspektisuuntautuneen€ohjelmoinnin

8

kehittämistä.  Järjestelmistä  saadaan  myös  helpommin  ymmärrettäviä,  muunneltavuus

paranee myös asiakaskohtaisesti samoin kuin uudelleen käytettävyys.

Aspektin muodostava koodi yhdistää poikkileikkaavasti ohjelmassa huolehdittavia asi­

oita    (crosscutting  concerns).  Tämä  modulaarinen  koodi  on  helpompi  käsitellä,  kuin

perinteisen  ohjelmiston  eri  osiin  tehty  koodi.  Myös  ohjelmiston  varsinainen  kohdetta

käsittelevä koodi on helpommin ymmärrettävissä, koska ohjelmoija voi kutsua aspektin

koodissa  esimerkiksi  erikseen  toteutettuja  hajautusalgoritmeja,  autentikointia,  avaus­

käskyjä (access control), synkronointia, salausta, automatisointia (redundancy). Aspektit

voivat  olla  uudelleen  käytettäviä  ja  ne  voivat  olla  liittimiä  (connector)  muihin  kom­

ponentteihin.

1.3 Näkymien muodostaminen ja sovelluksen ominaisuudet

Aspekti voi määrittelynä sisältää assosiaation muista ohjelman käsitteistä, kuten muut­

tujat  ja  metodit,  tyyppien  esittelyt,  poincut­määrittelyt    ja  advice­määrittelyt.  AOP­

tekniikassa aspekti muodostetaan valitsemalla ohjelman perustoiminnallisuuden luokis­

ta  join  point  ­kohdat,  joiden  suoritus  palvelee  kollektiivisesti  ohjelman  suoritusta

[ElF01].

Join  point  –kohdat  ovat  ohjelman  ydintoteutuksen  koodia,  jonka  toiminnallisuutta  as­

pekti hyödyntää. Ne voidaan ryhmitellä luonteensa mukaisesti suoritus­ , kutsu­ ja ken­

tän käytön tyyppisiin  join point –kohtiin:

Aspektissa voidaan viitata join point­kohtaan, joka suorittaa metodin, muuttujan alusta­

jan, konstruktorin, staattisen alustajan, käsittelijän tai objektin alustajan. Samoin aspek­

tissa voidaan viitata join point ­kohtaan, joka kutsuu metodin, konstruktorin ja objektin

esi­alustuksen. Join point ­kohta voi myös viitata kentän arvoon tai asettaa sen [LaC03].

Pointcut­määrittelyt voivat sisältää viittauksia useisiin join point ­kohtiin,  jotka vaikut­

tavat  aspektin  muodostukseen  eri  tavoin.  Pointcut­ määrittelyn  kautta  aspektien  koodi

Page 9: ASPEKTISUUNTAUTUNUT€OHJELMOINTI€€JA … · Luvussa€1€esitellään€aspektisuuntautuneen€ohjelmointitavan€historiaa€ja€käsitteistöä. Luvussa€2€esitellään€AspectJkieli,€joka€toteuttaa€aspektisuuntautuneen€ohjelmoinnin

9

on  vuorovaikutuksessa  järjestelmän  muun  koodin  kanssa.  Pointcut  voidaan  parametri­

soida haluttua käyttötarvetta tai käyttäjää varten.

Pointcut ­kohdat ovat useimmiten dynaamisia  eli voivat viitata  ohjelmassa  meneillään

oleviin  tapahtumiin  ja  muuttavat  ohjelman  käyttäytymistä.  Pointcut­lohkot  sisältävät

määrittäjän (pointcut designator eli pcd). Niissä voidaan määritellä halutut join point –

kohdat ja ehtoja niiden suorittamiselle.

Pointcut ­kohdan lisäksi aspektissa määritellään ohjeita (advice), nämä yhdessä vaikut­

tavat ohjelman etenemiseen käyttäen aspektissa toteutettuja palveluja järjestelmän koh­

detoimintojen toteuttamiseen. Kun ohjelma etenee advice­kohtaan, niiden koodi suorite­

taan. Advice­lohkon suoritus voi tapahtua ennen, jälkeen tai sen toiminnon sijaan mitä

lohkossa määritelty koodi kutsuu.

Tätä prosessia, joka saa aikaan sopivan advice­lohkon suorittamisen kussakin liitokses­

sa  kutsutaan  näkymän  koostamiseksi  (weaving).  Pointcut­määrittelyt  voivat  olla  myös

staattisia,  jolloin ne vaikuttavat lähinnä vain sovelluksen rakenteen muodostumiseen ja

tukevat dynaamisten poikkileikkauksellisten tehtävien toteuttamista [LaC03].

Tulkin (interpreter) suorittaessa ohjelmaa, se kutsuu saavuttamassaan pointcut­kohdassa

koostajaa (weaver), joka huolehtii join point­, advice­ ja pointcut­määrittelyjen mukais­

ten toimintojen liitosten valinnoista, niiden vaatimien ohjeiden kutsumisesta ja ohjeiden

mukaisesti valittujen ohjelman osien suorittamisesta [ElF01].

Koostesäännöt (weaving rules) määrittelevät ohjelman etenemisen vaiheissa ohjelmassa

suoritettavia  toimintoja.  AspectJ­kielessä  näitä  sääntöjä  ei  kirjoiteta  ydintoimintojen

toteutukseen,  vaan  ne  sisältyvät  näkymäkoodiin  ja  kääntäjän  sääntöihin.  [Lad03,

ElF01].

1.4 AOP:n vaikutus modularisointiin

Perinteisessä  olio­ohjelmoinnissa    selkeästi  eriytettyjä  ydintoimintoja  suorittavat  mo­

duulit  voidaan  toteuttaa  rajapintojen  avulla  ja    kytkeä  löysästi  toisiinsa.  Sovellukseen

Page 10: ASPEKTISUUNTAUTUNUT€OHJELMOINTI€€JA … · Luvussa€1€esitellään€aspektisuuntautuneen€ohjelmointitavan€historiaa€ja€käsitteistöä. Luvussa€2€esitellään€AspectJkieli,€joka€toteuttaa€aspektisuuntautuneen€ohjelmoinnin

10

pitää kuitenkin toteuttaa toimintoja, jotka vaikuttavat sen useissa osissa, niin palvelimel­

la kuin asiakassovelluksessa. Näitä toimintoja  kutsutaan poikkileikkauksellisiksi tehtä­

viksi (crosscutting concern).

Esimerkiksi käyttäjän auktorisointi  (authorization)  ­moduuli  voidaan  toteuttaa  rajapin­

nalla, jonka käyttö ei sido tiukasti asiakassovelluksen toteuttamista. Ohjelmoijan ei tar­

vitse  edes  tietää  auktorisointipalvelun  tarkkaa  toteutusta  käyttäessään  sitä  ja  palvelu

voidaan  myös  vaihtaa  toiseen  toteutukseen.  Kuitenkin  jokaisen  toteutukseen  sisältyy

palvelun käyttöön vaadittavaa koodia,  mikä sekoittuu peruslogiikan  toteuttamaan koo­

diin,  joten  palvelun  vaihtaminen  toiseen  ei  onnistu  ilman  suuria  muutoksia  järjestel­

mään.

Kuva 1 esittää  perinteisen olio­ohjelmoinnin tekniikalla toteutettuja pankkijärjestelmän

moduuleita;  Tili­,  Tilinsiirronhallinta­  ja  Tietokantamoduulit,  sekä  niiden  toimintoja

kirjoittava Lokimoduuli.  Lokimoduuli voidaan toteuttaa abstraktin API:n, joka piilottaa

yksityiskohtaisen toteutuksen. Kaikkien  muiden moduuleiden täytyy kuitenkin sisältää

tuota API:a kutsuvaa koodia.

AOP­tekniikkaa  käytettäessä  ydintoimintojen  moduulit  eivät  sisällä  API­kutsuja,  eikä

niissä tarvitse olla tietoisia  Loki­moduulista, joka Loki­aspektin kanssa huolehtii lokin

kirjoittamisesta,   katso kuva 2. Jos  tähän sovelluksen poikkileikkaukselliseen  lokinkir­

joitus  tehtävään  syntyy  uusia  vaatimuksia,  tarvitsee  muutoksia  tehdä  vain  Loki­

aspektiin,  joka  huolehtii  tietojen  sieppaamisesta  ja  kutsuu  lokia  kirjoittavaa  API:a.

Asiakasmoduulit eivät sisällä lokin kirjoittamiseen liittyvää koodia.

Page 11: ASPEKTISUUNTAUTUNUT€OHJELMOINTI€€JA … · Luvussa€1€esitellään€aspektisuuntautuneen€ohjelmointitavan€historiaa€ja€käsitteistöä. Luvussa€2€esitellään€AspectJkieli,€joka€toteuttaa€aspektisuuntautuneen€ohjelmoinnin

11

Kuva 1.  Moduulien toteutus perinteisellä tekniikalla. API­kutsut kytkevät

moduulit  toisiinsa [Lad03].

Kuva 2. AOP­tekniikalla toteutettu pankkijärjestelmän lokinkirjoitus. Aspekti määritte­

lee sieppauskohdat ja kutsuu niitä suoritettaessa lokia kirjoittavaa API:a [Lad03].

Loki aspekti

Tietokantamoduuli

Tilisiirronmoduuli

Tili moduuliAutomaattisesti

muodostetut kutsut

Loki moduliAPI kutsut

Loki moduuli

Tietokantamoduuli

Tilisiirronmoduuli

Tili moduuliAPI kutsut

Page 12: ASPEKTISUUNTAUTUNUT€OHJELMOINTI€€JA … · Luvussa€1€esitellään€aspektisuuntautuneen€ohjelmointitavan€historiaa€ja€käsitteistöä. Luvussa€2€esitellään€AspectJkieli,€joka€toteuttaa€aspektisuuntautuneen€ohjelmoinnin

12

Sovellusten poikkileikkauksellisten  tehtävien  modularisointi  tekniikoita on useita. Esi­

merkiksi Enterprise JavaBeans (EJB) –arkkitehtuuri yksinkertaistaa hajautettujen palve­

linpuolen sovellusten luomista ja laajojen tehtävien käsittelyä, kuten turvallisuuden (se­

curity), hallinta (administration), suorituskyky (performance) sekä säiliöinnin pysyvyys

(container­managed persistence). Java­papujen kehittäjät voivat keskittyä liiketoiminta­

logiikkaan tai toisaalta asennusnäkymässä pavun datan kartoittamiseen tietokannan da­

tan kanssa. Näin  EJB­kehyksessä voidaan eriyttää erillisiksi tehtäviksi  liiketoimintalo­

giikka  ja asennuskuvauksen (deployment descriptor) avulla datan kartoitus pavun ken­

tistä tietokannan sarakkeisiin. Asennuskuvaus on kartoituksen XML­tiedosto [Lad03].

Toinen poikkileikkauksellisten tehtävien modularisointitekniikka  on dynaamisten pro­

xien  käyttäminen    proxy­suunnittelumallin  mukaisesti.  Tämä  on  monimutkainen  tek­

niikka, jota ei käsitellä tässä raportissa.

Modularisoimattomuus aiheuttaa  järjestelmän koodin sekaisuuden,  jos yksittäinen  mo­

duuli on  toteutettu niin, että  se huolehtii useista  eri  tehtävistä  samanaikaisesti. Yhteen

tehtävään  liittyvää koodia  joudutaan myös  levittämään useisiin  moduuleihin,  joten oh­

jelmiston muutokset ovat työläitä ja alttiita virheille.

1.5 AOP­kielinen implementointi

AOP­metodologian  mukainen  järjestelmän  kehittäminen  etenee  periaatteeltaan  tavan­

omaisesti. Tunnistetaan tehtävät (concern),  implementoidaan ne  ja muodostetaan niistä

yhdistämällä  lopullinen  järjestelmä.  Tehtävien  tunnistamiseksi  vaatimukset  jaotellaan

yksittäisiin  ydintehtäviin    (core  concerns)  ja  järjestelmätason  poikkileikkauksellisiin

tehtäviin (crosscutting  concerns). Ensin mainittuja ovat esimerkiksi ydin liiketoiminnan

tehtävät ja järjestelmätasolla monen moduulin alueelle vaikuttavia ovat esimerkiksi aut­

horisointi, lokin kirjoitus, pysyvyys, säieturvallisuus ja puskurointi.

Seuraavassa  vaiheessa  jokainen  näistä  tehtävistä  implementoidaan  itsenäisesti.  Ydin

tehtävien  toteutukseen  voidaan  käyttää  tavanomaista  olio­ohjelmointi  tekniikkaa,  eli

Page 13: ASPEKTISUUNTAUTUNUT€OHJELMOINTI€€JA … · Luvussa€1€esitellään€aspektisuuntautuneen€ohjelmointitavan€historiaa€ja€käsitteistöä. Luvussa€2€esitellään€AspectJkieli,€joka€toteuttaa€aspektisuuntautuneen€ohjelmoinnin

13

koodataan  perustoiminnallisuuden  ja  rakenteet  sisältävät  ohjelmointikieliset  rajapinnat

ja luokat.

Lopuksi määritellään koostamissäännöt aspekteille,  jotka muodostavat modularisoinnin

yksiköt. Aspektien sisältämän   informaation perusteella muodostuu lopullisen järjestel­

män toiminnallisuus. Esimerkiksi aspektissa voidaan määritellä, että jokaisen sovelluk­

sen operaation  pitää  varmistua  asiakkaan  oikeuksista  ennenkuin  sovellus  etenee  liike­

toimintalogiikkaan [Lad03].

Kieliriippumaton  AOP­toteutus  muodostuu  kaksivaiheisesti:  ensin  yhdistetään  erilliset

tehtävät koostesääntöjen (weaving rules) mukaisesti. Koostesäännöt määritellään aspek­

teissa.  Ne  voivat  olla  eri  ohjelmointikielisiä  toteutuksia  kuin  ydintehtävien  toteutus.

Kääntävälle prosessorille  voidaan  antaa ohjeeksi  eri  lähdekoodisia käännöksiä  lopulli­

sen  suoritettavan  koodin  muodostamiseksi,  mikä  vaatii  kuitenkin  työläitä  käännösvai­

heita.

Kuva 3 esittää aspektien ja ydintehtävien toteutuksen yhdistämisen koostamissääntöjen

mukaisesti  järjestelmäksi.  Tässä  koostaja  (weaver)  sisältyy  AOP­kääntäjään  (AOP

Compiler). Koostesäännöt (weaving rules) määrittelevät poikkileikkaukselliset  tehtävät

ja antavat lisätoiminnallisuutta ydintehtävien toteutukseen, joten niiden lähdekoodiin ei

tarvitse tehdä muutoksia. Koostaminen ilmenee vain kääntäjän tuottamassa tavukoodis­

sa. Ydintehtävien  toteutus voi  sisältää  java­lähdekoodia  ja  ­luokkatiedostoja.  Järjestel­

mä sisältää koostetun ryhmän luokkatiedostoja.

Page 14: ASPEKTISUUNTAUTUNUT€OHJELMOINTI€€JA … · Luvussa€1€esitellään€aspektisuuntautuneen€ohjelmointitavan€historiaa€ja€käsitteistöä. Luvussa€2€esitellään€AspectJkieli,€joka€toteuttaa€aspektisuuntautuneen€ohjelmoinnin

14

AOP­kääntäjä

(AOP Compiler)Järjestelmä

Ydintehtävientoteutus

(Core concernimplementation)

Koostesäännöt(Weaving Rules)

Kuva 3. AOP kääntäjä toimii lopullisen järjestelmän koostajana (wiever) [Lad03].

Tässä  raportissa  perehdytään  aspektien  toteutukseen  vain  Java­ympäristössä  käyttäen

valmista AspectJ­kääntäjää. Ympäristön tarkempi  selvitys on liitteessä 1.

Page 15: ASPEKTISUUNTAUTUNUT€OHJELMOINTI€€JA … · Luvussa€1€esitellään€aspektisuuntautuneen€ohjelmointitavan€historiaa€ja€käsitteistöä. Luvussa€2€esitellään€AspectJkieli,€joka€toteuttaa€aspektisuuntautuneen€ohjelmoinnin

15

2 ASPECTJ

AspectJ­ohjelmointikieli  on  aspektisuuntautunut  Java­kielen  laajennus,  joten  Java­

kielinen  ohjelma  on  myös  kelvollinen  AspectJ­ohjelma.  AspectJ­kääntäjä  (compiler)

kääntää  lähdekoodin  luokkatiedostoiksi,  jotka  ovat  yhdenmukaisia  Javan  tavukoodin

kanssa, joten Javan virtuaalikone pystyy suorittamaan nämä luokkatiedostot.

AspectJ­käännöksessä  toteutuvat  dynaaminen    ja  staattinen  poikkileikkauksellisuus.

Dynaaminen poikkileikkauksellisuuden (dynamic crosscutting)  koostaminen tarkoittaa

uuden  toiminnon  tai käytöksen kutomista  (weaving) ohjelman suoritukseen. Näin voi­

daan ottaa käyttöön  tai korvata  ydintoteutuksen  moduulien  toimintoja ohjelman suori­

tuksessa [Lad03].

Staattinen poikkileikkauksellisuuden (static crosscutting)  koostaminen ei muuta ohjel­

man käytöstä suorituksen aikana, vaan sen staattista rakennetta, kuten luokkia, rajapin­

toja ja aspekteja. Esimerkiksi luokkiin ja rajapintoihin voidaan lisätä uusia metodeja tai

dataa, jotta luokkien tilan ja käytöksen avulla voidaan toteuttaa dynaamista poikkileik­

kauksellisuutta. Staattista poikkileikkauksellisuutta ovat myös käännöksen aikaiset va­

roitukset ja virheilmoitukset, joilla ohjataan moduulien toteuttamista.

Java­kielen  AspectJ­laajennukset  määrittelevät  dynaamisen    ja  staattisen poikkileikka­

uksellisuuden  koostesääntöjä  (weaving  rules).  AspectJ­laajennuksissa  käytetään  join

point­,  pointcut­  ja  advice­määrittelyjä,  jotka  ovat ohjelmallisia  koostesääntöjä. Nämä

määrittelyt muodostavat moduuleja,  jotka toteuttavat  jonkin poikkileikkauksellisen teh­

tävän sovelluksessa [Lad03].

2.1 Join point

Join point on tunnistettava kohta ohjelman  lähdekoodissa  ja suorituksessa. Se voi olla

metodin  kutsu  tai  objektin  jäsenen  määrääminen  (assignment).  AspectJ­kielessä  join

Page 16: ASPEKTISUUNTAUTUNUT€OHJELMOINTI€€JA … · Luvussa€1€esitellään€aspektisuuntautuneen€ohjelmointitavan€historiaa€ja€käsitteistöä. Luvussa€2€esitellään€AspectJkieli,€joka€toteuttaa€aspektisuuntautuneen€ohjelmoinnin

16

point  on  hyvin  keskeinen,  koska  ne  ovat  ohjelman  luokkatoteutuksen  kohtia,  joista

poikkileikkaukselliset toiminnot kerätään. Esimerkiksi seuraavassa luokan määrittelyssä

voi  löytää  kaksi  join  point  –kohtaa:  suoritettava credit()­metodi  ja _balance­

instanssijäsenen käyttö.

public class Account {

void credit(float amount) {

_balance += amount;

}}

Koska join point on jokin kohta ajettavan ohjelman dynaamisten kutsujen graafissa, sen

käyttäytymistä  voidaan  muuttaa,  esimerkiksi  aspektin  advice­lohkon  ohjeella.  Jokaista

dynaamista join point­kohtaa vastaa jokin lähdekoodin nimetty osa. Erilaiset join point­

kohtien  lajit  lähdekoodissa  ja  niitä  vastaavat  tunnisteet  (signature)  on  lueteltu  seuraa­

vassa  taulukossa. Näitä kohtia  voidaan  määrittää  lähdekoodista  joko tunnisteen perus­

teella suoraan tai reflektoimalla [Lad03].

Taulukko 1.   Join poin lajit ja niiden tunnisteet

Join point­laji Tunniste lähdekoodissa (signature)

Metodin suoritus Metodi

Metodin kutsu Metodi

Konstruktorin suoritus Konstruktori

Kentän saanti (get) Kenttä

Kentän asetus (set) Kenttä

Advice­lohkon suoritus  ­

Alustus Vastaava konstruktori

Staattinen alustus Tyypin nimi

Page 17: ASPEKTISUUNTAUTUNUT€OHJELMOINTI€€JA … · Luvussa€1€esitellään€aspektisuuntautuneen€ohjelmointitavan€historiaa€ja€käsitteistöä. Luvussa€2€esitellään€AspectJkieli,€joka€toteuttaa€aspektisuuntautuneen€ohjelmoinnin

17

Esi alustus Vastaava konstruktori

Poikkeuksen käsittelijä Poikkeuksen tyypin nimi

Poikkeuksen heitto Poikkeuksen tyypin nimi

Synkronointi Lukitusobjektin tyypin nimi

Taulukko 1 esittää join point –lajit sekä tunnisteet,  joiden perusteella näitä kohtia voi­

daan  määrittää  lähdekoodista. Advice­lohko määritellään aspektissa,  jossa  se ohjeistaa

join point –kohdan suoritusta [HiH04].

2.2 Pointcut

Pointcut on ohjelmarakenne, joka valitsemalla join point­kohdat ja kokoaa näiden koh­

tien kontekstin. Esimerkiksi pointcut voi valita metodin kutsun, ja voi myös siepata me­

todin kontekstin, kuten metodin kutsuman kohdeobjektin sekä metodin argumentit. Näin

pointcut määrittelee koostesäännön (weaving rule),  jonka  joint point­kohta tilannekoh­

taisesti  täyttää. Edellisen  luvun 2.1 esimerkin  jatkona voidaan kirjoittaa pointcut,  joka

sieppaa credit()­metodin suorituksen:

execution(void Account.credit(float))

AspectJ:n  pointcut­mekanismi  sisältää  join  point  –kohtien  valintaoperaattoreita,  joita

kutsutaan primitiivisiksi  pointcut  määrittäjiksi  (primitive  pointcut  designator,  pcd).

Pointcut­lohkoissa nämä määrittäjät valitsevat sellaisia joinpoint­tyyppejä, joiden meta­

datan kuvaus täsmää määrittäjän argumentteihin, katso taulukko 1.

Nämä argumentit voivat perustua joinpoint­kohdan nimeen (signature) tai tyypin kuva­

ukseen (type pattern), joiden ilmaisemiseen voidaan käyttää jokerimerkkejä (wildcards).

Pointcut­lohkon  määrittäjät  voivat  tunnistaa  myös  toisen  pointcut­lohkon  määrittelyn

joinpoint­kohdat  ja  liittää  ne  kontrollivirtaansa.  Määrittäjä  voi  valita  joinpoint­kohdat

myös niiden suorituksen kontekstissa käytettävien objektien ja argumenttien perusteella.

Näin  ollen  primitiiviset  pointcut määrittäjät  voidaan  jakaa  argumenttiensä  perusteella

kolmeen categoriaan, katso taulukot 2, 3 ja 4.  [LaC03]

Page 18: ASPEKTISUUNTAUTUNUT€OHJELMOINTI€€JA … · Luvussa€1€esitellään€aspektisuuntautuneen€ohjelmointitavan€historiaa€ja€käsitteistöä. Luvussa€2€esitellään€AspectJkieli,€joka€toteuttaa€aspektisuuntautuneen€ohjelmoinnin

18

Taulukko 2.   Tyypin kuvaukseen tai nimeen perustuva pointcut­lohkon määrittäjä

Määrittäjä (designator) Valitut join point ­kohdat

call(Signature) metodien ja konstruktorien kutsut

execution(Signature) metodien ja konstruktorien suoritus

initialization(Signature) objektin alustuksen suoritus

get(Signature) kentän viittaus

set(Signature) kentän asetus

staticinitialization(TypePattern) staattisen alustajan suoritus

within(TypePattern) kaikki  tyypin  mukaiset  join  point­kohdat

withincode(Signature) metodien ja konstruktorien määrittelyt

Taulukossa  2  luetellaan  määrittäjät,  jotka  valitsevat  joinpoint­kohdat  nimen  tai  tyypin

kuvauksen perusteella [LaC03].

Taulukko 3.   Pointcut­perusteinen määrittäjä

Määrittäjä (designator) Valitut join point ­kohdat

cflow(pointcut) kaikki suorituksessa käytetyt joinpoint­kohdat jotkapointcut määrittää

cflowbelow(pointcut) kuten cflow,  mutta  ei  sisällä  argumenttinä  olevapointcut­lohkon join point­kohtia

Taulukossa  3  luetellaan  määrittäjät,  jotka  valitsevat  joinpoint­kohdat  toisen  pointcut­

lohkon määrittelyn perusteella [LaC03].

Page 19: ASPEKTISUUNTAUTUNUT€OHJELMOINTI€€JA … · Luvussa€1€esitellään€aspektisuuntautuneen€ohjelmointitavan€historiaa€ja€käsitteistöä. Luvussa€2€esitellään€AspectJkieli,€joka€toteuttaa€aspektisuuntautuneen€ohjelmoinnin

19

Taulukko 4.   Konteksti­perusteinen määrittäjä

Määrittäjä (designator) Valitut join point ­kohdat

this(TypePattern or Id) joinpoint­kohdat joissa this­määreellä sidot­tu objekti on tietyn tyypin ilmentymä

target(TypePattern or Id) joinpoint­kohdat  joissa  kutsu  tai  kenttä­operaatio kohdistuu  tietyn tyyppisen objektinilmentymään

args(TypePattern or Id, ...) joinpoint­kohdat  joiden argumentit täsmäävätmäärittäjän argumetteihin

Taulukossa 4 luetellaan määrittäjät, jotka valitsevat joinpoint­kohdat niiden suoritukses­

sa käytettävien objektien ja argumenttien perusteella. Nämä sisältävät myös suorituksen

kontekstin [LaC03].

2.3 Advice

Advice  –koodi  suoritetaan  siinä  join  point­kohdassa,  joka  pointcut­määrittelyssä      on

valittu. Advice­koodi  voidaan  suorittaa ennen  join point­kohtaa tai  sen  jälkeen,  se voi

myös  ohittaa  kohdan  tai  korvata  sen.  Advice­koodi  voi  esimerkiksi  kirjoittaa  viestin

ennen  kuin  eri  moduleissa  olevat  join  point  ­kohdat  suoritetaan.  Advice­määrittelyn

runko muistuttaa metodin runkoa, sillä se kapseloi suoritettavan logiikan metodiin siir­

ryttäessä.  Esimerkiksi  seuraava  advice  tulostaa  viestin  ennenkuin  suorittaa  Account­

luokan credit()­metodin.

before() : execution(void Account.credit(float)) {

System.out.println(“ Veloitetaan”);}

Pointcut  ja  advice  yhdessä  muodostavat  dynaamisen  poikkileikkaussäännön.  Pointcut

tunnistaa vaaditun join point –kohdan,  ja advice­lohkon ohjeet täydentävät  join point –

kohtien  toimintoja.  Ohjeita  voidaan  määritellä  suorituksensa  ja  käyttötarkoituksensa

mukaisesti seuraavasti:

Page 20: ASPEKTISUUNTAUTUNUT€OHJELMOINTI€€JA … · Luvussa€1€esitellään€aspektisuuntautuneen€ohjelmointitavan€historiaa€ja€käsitteistöä. Luvussa€2€esitellään€AspectJkieli,€joka€toteuttaa€aspektisuuntautuneen€ohjelmoinnin

20

­ before()­advice suoritetaan ennenkuin ohjelman suoritus etenee käsiteltävänä ole­

vaan join point ­kohtaan. Esimerkiksi:

before(): move() {

     System.out.print(”lähtee”);}

­ after()returning  ja after()throwing –advice  suoritetaan, kun  join point  ­

kohta on palauttanut  jotain tai heittänyt poikkeuksen. Pelkkä after()­advice voidaan

suorittaa molemmissa tapauksissa. Esimerkki palautuksesta:

after(FigureElement fe, int x, int y) returning:

   call (void FigureElement.setXY(int, int))

   && target(fe)

   && args(x,y) {

   System.out.println(fe + “ moved to (“ + x +“,”+y+”)”); }

­ around()­advice  suoritetaan  käsiteltävänä  olevan  join  point  ­kohdan  sijaan.  Join­

point­kohdan  alunperäistä  toiminnallisuutta  voidaan  kutsua käyttämällä proceed()  –

kutsua [HiH04].

Esittely  (Introduction)  on  staattinen  poikkileikkaava  käsky,  joka  esittelee  muutoksia

sovelluksen  luokkiin,  rajapintoihin  ja  aspekteihin.  Se  saa  aikaan  staattisia  muutoksia

moduuleihin,  mutta  ei  vaikuta  suoraan  niiden  käytökseen.  Esimerkiksi  luokkaan  voi­

daan  lisätä  metodi  tai kenttä. Esimerkiksi  seuraavassa  esittely  ilmoittaa,  että Account­

luokka toteuttaa BankingEntity­rajapinnan:

declare parents: Account implements BankingEntity;

Käännöksen  aikaiset  ilmoitukset  (compile­time  declarations)  ovat  staattisia  poikki­

leikkaavia ohjeita, joilla voidaan esimerkiksi ehkäistä väärää koodaustapaa. Esimerkiksi

voidaan  ilmoittaa,  että  on  virhe  kutsua  Abstract  Window  Toolkit  (AWT)­koodia

Page 21: ASPEKTISUUNTAUTUNUT€OHJELMOINTI€€JA … · Luvussa€1€esitellään€aspektisuuntautuneen€ohjelmointitavan€historiaa€ja€käsitteistöä. Luvussa€2€esitellään€AspectJkieli,€joka€toteuttaa€aspektisuuntautuneen€ohjelmoinnin

21

EJB:stä. Seuraava käännöksen aikainen ilmoitus saa kääntäjän varoittamaan, jos jostain

järjestelmän  osasta  kutsutaan  Persistence­luokan save()­metodia.  Tällöin call()­

pointcut sieppaa metodin kutsun.

declare warning : call(void Persistence.save(Object))

:  “  Consider using Persistence.saveOptimized()  “ ;

Aspekti  (aspect)  on  yhtä  keskeinen  yksikkö  AspectJ­kielessä  kuin  luokka  on  Java­

kielessä. Aspektin koodi  ilmaisee sekä dynaamisen että staattisen poikkileikkaavuuden

koostesäännöt. Aspekti yhdistää pointcut­ ja advice­määrittelyt, sekä ilmoitukset ja esit­

telyt. Näiden AspectJ­elementtien lisäksi aspekti voi sisältää dataa, metodeja ja sisäluo­

kan jäseniä, samalla tavalla kuten java­luokkakin. Edellä olevien esimerkkejä  käyttäen

voidaan kirjoittaa seuraavanlainen aspekti:

public aspect EsimerkkiAspekti {

  before() : execution(void Account.credit(float)) {

  System.out.println(“ Tulostettava viesti”);

  }

  declare parents: Account implements BankingEntity;

  declare warning: call(void Persistence.save(Object))

    : “Consider using Persistence.saveOptimized()“ ;

}

Aspektissa voidaan määritellä sisäluokkia samoin kuin luokissa sisäaspekteja. Staattinen

aspekti voi esitellä luokalle uusia jäseniä. Aspektin instanssi voi ohjeistaa (advice) sekä

luokan että aspektin instanssin jäseniä [Ken99].

Page 22: ASPEKTISUUNTAUTUNUT€OHJELMOINTI€€JA … · Luvussa€1€esitellään€aspektisuuntautuneen€ohjelmointitavan€historiaa€ja€käsitteistöä. Luvussa€2€esitellään€AspectJkieli,€joka€toteuttaa€aspektisuuntautuneen€ohjelmoinnin

22

3 SUUNNITTELUMALLIT

Tässä luvussa tutkitaan Worker­objektin luonti ­, Madonreikä ­, Poikkeuksen esittely­ ja

Osapuoli –suunnittelumalleja. Malleja käytetään tässä raportissa kehitettävän sovelluk­

sen toteutuksessa. Suunnittelumallien lähdekoodit ovat raportin sähköisessä liitteessä.

3.1 Worker­objektin luonti ­ suunnittelumalli

Worker­objekti on  luokanilmentymä,  joka kapseloi metodin niin, että metodia voidaan

käyttää  kuten  objektia.  Tuota  metodia  kutsutaan  Worker­metodiksi.  Worker­objektia

voidaan kutsua,  välittää toiseen paikkaan ja varastoida. Yleinen tapa toteuttaa tällainen

Worker­objekti  on Runnable  –rajapinnan  käyttö,    jonka  toteuttava  luokka  sisältää

run()­metodin  joka  puolestaan  kutsuu  Worker­metodia.  Worker­objektin  suoritus

(execution) edelleen suorittaa Worker­metodin.

Tätä suunnittelumallia voidaan käyttää sieppamaan  operaatioita pointcut­määrittelyjen

kanssa.  Voidaan  myös  automaattisesti  generoida  Worker­objekteja  jotka  kapseloivat

nuo operaatiot. Näitä objekteja voidaan välittää sopiville metodeille suoritettavaksi.

Tässä  esiteltävässä  mallissa  käytetään  aspektia  luomaan  automaattisesti  anonyymien

worker­luokkien objekteja. Nämä objektit ovat Worker­objekteja. Aspektiin kirjoitetaan

pointcut,  joka  sieppaa  kaikki  ne  join  point­kohdat,  jotka  on  ohjattava  Worker­

objekteille.  Seuraavaksi  kirjoitetaan  advice  joka  suorittaa  nämä  siepatut  join  point­

kohdat anonyymien worker­luokkien run()­metodissa.

Tavallisesti  around  advice –lohkossa  suoraan  kutsuttu proceed()  –metodi  suorittaa

siepatut join point –kohdat. Tässä mallissa proceed() –metodia kutsuu around advice

joka on Runnable­rajapinnan implementoivan anonyymin luokan sisältämässä run()­

metodissa, ja saa Worker­objektin palautteena. Tämän objektin run()­metodia voidaan

käyttää esimerkiksi säikeissä suorittamaan siepatut join point –kohdat.

Page 23: ASPEKTISUUNTAUTUNUT€OHJELMOINTI€€JA … · Luvussa€1€esitellään€aspektisuuntautuneen€ohjelmointitavan€historiaa€ja€käsitteistöä. Luvussa€2€esitellään€AspectJkieli,€joka€toteuttaa€aspektisuuntautuneen€ohjelmoinnin

23

Seuraavaa mallin kaavaa voi käyttää implementointiin. Ensin kirjoitetaan pointcut joka

sieppaa halutut join point ­kohdat. Koska kaavassa ei tarvita kontekstia, voidaan käyttää

nimettyä  tai anonyymiä pointcut­määrittelyä. Seuraavaksi pointcut ohjeistetaan kirjoit­

tamalla  siihen  around  advice,  jonka  rungossa  luodaan  anonyymin  luokan  Worker­

objekti.  Se  luodaan  kutsumalla run()  ­metodissa proceed()  ­metodia  sen  sijaan,

että kutsuttaisiin  jotain tiettyä metodia. Tämän  jälkeen Worker­bjektia voidaan käyttää

halutulla tavalla.

void around() : <pointcut> {

   Runnable worker = new Runnable () {

      public void run() {

              proceed();

}}

... Lähetä worker­objekti johonkin jonoon suoritettavaksi,

... tai lähetä worker­objekti jollekin alijärjestelmälle

    suoritettavaksi,

... tai kutsu pelkästään run() –metodia suoraan.

}

Esimerkki kaavan käyttämisestä [Lad03]:

Liitteessä  2  on  uudelleen  käytettävän  abstraktin Asynchronous­

ExecutionAspect    ­aspektin  lähdekoodi.  Aspekti  suorittaa  erillisessä  säikeessä

kaikki join point ­kohdat, jotka asyncOperations() –niminen pointcut määrittelee.

Aspekti sisältää abstraktin pointcut­esittelyn, sekä around advice ­ohjeen sille.

Aspektin    advice  ­runko  luo  anonyymin  luokan  objektin,  joka  implentoi Runnable­

rajapinnan. Run()­metodi kutsuu proceed()­metodia,  joka suorittaa join point –kohdat.

worker  –objekti  suorittaa ohjeistetut  joint  point  –kohtien  operaatiot.  Advice  käyttää

sitä uuden säikeen luomiseen ja aspekti käynnistää luodun säikeen.

Page 24: ASPEKTISUUNTAUTUNUT€OHJELMOINTI€€JA … · Luvussa€1€esitellään€aspektisuuntautuneen€ohjelmointitavan€historiaa€ja€käsitteistöä. Luvussa€2€esitellään€AspectJkieli,€joka€toteuttaa€aspektisuuntautuneen€ohjelmoinnin

24

AsynchronousExecutionAspect ­aspektissa esitelty abstrakti pointcut määritel­

lään konkreettisessa aliaspektissa.

Liitteen  2 SystemAsynchronousExecutionAspect­aspekti  sisältää  tarvittavan

pointcut  –määrittelyn.  Aspektissa  määritellään  ohjelmallisesti  varmuuskopion  teko  ja

nouto  välimuistista  tapahtumaan  eri  säikeissä. SystemAsynchronousExecu­

tionAspect  mahdollistaa CachePreFetcher­  ja Projectsaver­    luokkien

metodien  asynkronisen    suorituksen.  Näiden  luokkien  ja Test­luokan  lähdekoodi  on

liitteessä 2.

Nämä  voidaan  kääntää  ajc­komennolla,  joka  vastaa  Java­kielen  javac­komentoa,  sekä

ajaa normaalisti java­komennolla:

> ajc CachePrefetcher.java ProjectSaver.java Test.javaAsynchronousExecutionAspect.java SystemAsynchronousExe­cutionAspect.java

> java Test

Tulosteena saadaan CachePrefetcher ja ProjectSaver –luokkien viestit ja säi­

keiden nimet.

3.1.1 Worker­metodin palauttama arvo

Edellisen kappaleen esimerkkin ohjatut kutsut voivat palauttaa arvon kutsujalle. Tällöin

proceed() palauttaa metodin arvon, kun operaatio on suoritettu loppuun. Tämän ar­

von voi pitää Worker­objektissa tai palauttaa around advice –lohkosta. Jotta arvo olisi

järkevä,  kutsujan  pitää  odottaa  kunnes  Worker­objektin  suoritus  on  päättynyt.  Edellä

kerrotussa asynkronisessa esimerkissä kutsuvan säikeen palauttama arvo ei vastaa ope­

raation  arvoa,  koska  säie  palauttaa  arvon  välittömästi  ja  operaatio  voidaan  suorittaa

myöhemmin.

Paluuarvo  voidaan  ottaa  talteen  yleisellä  tavalla,  esimerkiksi  kirjoittamalla  abstrakti

luokka RunnableWithReturn, joka implementoi Runnable –rajapinnan. Runna­

bleWithReturn­luokkaa  implementoivissa    luokkissa run() –metodin pitää aset­

Page 25: ASPEKTISUUNTAUTUNUT€OHJELMOINTI€€JA … · Luvussa€1€esitellään€aspektisuuntautuneen€ohjelmointitavan€historiaa€ja€käsitteistöä. Luvussa€2€esitellään€AspectJkieli,€joka€toteuttaa€aspektisuuntautuneen€ohjelmoinnin

25

taa _returnValue­jäsen proceed()­metodin palautusarvoksi, koska se on suorite­

tun  join  point  –kohdan  palautusarvo.  RunnableWithReturn­luokan  lähdekoodi  on  liit­

teessä 2.

Tätä RunnableWithReturn­luokkaa  voidaan  käyttää  perusluokkana  anonyymille

luokalle  advice­lohkossa,  kuten  liitteen  2 SynchronousExecutionAspect­

aspektissa.  Around  advice  –lohkon proceed()­metodin  paluuarvo  on  asetettu

_returnValue­jäsenen arvoksi. proceed()­metodin palauttama objekti on kääre­

objekti (wrapper), joten paluuarvon tyypistä ei tarvitse huolehtia.

Worker­objektin  luonti  ­suunnittelumallia  voi  hyödyntää  erilaisissa  tilanteissa,  kuten

auktorisoinnissa  ja  säieturvallisuudessa  myös  Swing­komponenttien  kanssa.  Worker­

objektia voi  joissakin tilanteissa käyttää heti  luonnin  jälkeen, koska se  ilmentää silloin

kontekstia. Näin tehdään esimerkiksi tämän raportin transaktionhallinnan esimerkissä.

3.1.2 Worker­objektin kontekstin hallinta

Worker­objektin  luonti  –suunnittelumallin  soveltamisessa  voi  olla  tarpeellista  koota

pointcut­kohdan  konteksti  talteen  muuta  käyttöä  varten.  Muuttumattoman  kontekstin

saa talteen ja välitettäväksi advice­lohkossa proceed() –metodin avulla seuraavasti:

void around([context]) : <pointcut> {

    Runnable worker = new Runnable() {

      Proceed([context]);

 }}

   ... voit käyttää worker­objektia

}

Page 26: ASPEKTISUUNTAUTUNUT€OHJELMOINTI€€JA … · Luvussa€1€esitellään€aspektisuuntautuneen€ohjelmointitavan€historiaa€ja€käsitteistöä. Luvussa€2€esitellään€AspectJkieli,€joka€toteuttaa€aspektisuuntautuneen€ohjelmoinnin

26

3.2 Madonreikä suunnittelumalli

Madonreikä  suunnittelumalli  (Wormhole  pattern)  välittää  kutsujan  informaation  kon­

tekstin  kutsunvastaanottajan  käytettäväksi  ilman,  että  informaatiota  tarvitsisi  välittää

kontrollivirrassa (control flow) kullekin metodille parametrijoukkona. Esimerkiksi auk­

torisoinnissa järjestelmän usean metodin on tiedettävä, kuka niitä kutsui, jotta ne voisi­

vat  päätellä  onko  kutsujalla  lupa  tähän  operaatioon.  Madonreikäsuunnittelumalli  sallii

käyttää kutsuvaa objektia ja sen kontekstia tämän tiedon hankkimiseen.

Malli  luo suoran  reitin kahden  tason välille kutsupinossa  (call  stack),  jolloin  vältytään

kaikkien tasojen läpikäymiseltä. Tämä säästää kutsuketjun modifioinnilta kun halutaan

välittää kontekstin informaatiota, se myös ehkäisee niin sanottua API­saastetta.

Jos AspectJ ei ole käytössä, voi monisäikeisessä ympäristössä välittää kutsujan konteks­

tin kahdella  tavalla. Voit välittää kontekstin  informaation  lisäparametrien avulla,  mikä

aiheuttaa  API  –saastetta,  koska  kaikille  metodeille  pitää  määritellä  ylimääräisiä  para­

metrejä. Toinen tapa on käyttää kutsujan luomia säiekohtaisia varastoja kontekstin aset­

tamiseksi  ja käyttämiseksi. Tässäkin tavassa useat moduulit ovat mukana informaatiota

välittävässä logiikassa.

3.2.1 Madonreikä suunnittelumallin periaate

Malli voidaan  luoda määrittelemällä kaksi pointcut­kohtaa: yksi kutsujalle  ja  yksi kut­

sun  vastaanottajalle.  Kutsuja  kokoaa  kontekstin  mikä  välitetään  tässä  madonreiässä.

Madonreikä on määriteltävä vastaanottajan join point­kohtien suorituskohdista kutsujan

join point­kohtien kontrollivirtaan.

Kuva 4 esittää kutsupinoa  tasoittain. Normaalisti  konteksti  voidaan siirtää  taso kerral­

laan, kunnes haluttu taso saavutetaan. Madonreikä mallissa tehdään polku suoraan ha­

luttujen tasojen välille.

Page 27: ASPEKTISUUNTAUTUNUT€OHJELMOINTI€€JA … · Luvussa€1€esitellään€aspektisuuntautuneen€ohjelmointitavan€historiaa€ja€käsitteistöä. Luvussa€2€esitellään€AspectJkieli,€joka€toteuttaa€aspektisuuntautuneen€ohjelmoinnin

27

Kunkin tasonkonteksti

Kutsuja

Kutsuttu

Kutsu­pino

Madonreikä

Kuva  4.  Madonreikämalli  välittää  kutsuttavan  objektin  kontekstin  kutsupinon  tasojen

ohi suoraan kutsujalle. Vaakatasot esittävät kutsun syvyyttä.

3.2.2 Madonreikämallin kaava

Mallin  kirjoittamiseen  voidaan  käyttää  seuraavaa  kaavaa,  jossa  määritellään  kutsuvan

tilan pointcut, joka kokoaa siihen liittyvän kontekstin. Samoin määritellään kutsun vas­

taanottajan  tilan  pointcut.  Koottu  konteksti  voi  molemmissa  tiloissa  olla  kohdeobjekti

tai muu parametri tarvittaville metodeille ja niiden suoritus.

Seuraavaksi luodaan pointcut joka toteuttaa madonreiän. Sekä kutsujan että kutsun vas­

taanottajan pointcut­lohkot  sieppaavat omassa  tilassaan  join point –määrittelyistä kon­

tekstinsa. pointcut wormhole ­lohkossa kutsun vastaanottajan calleeSpace()

pointcut  määritellään  samaan  kontrollivirtaan  kutsujan callerSpace()  pointcut­

kutsujen kanssa. Näin saadaan molempien join point –määrittelyjen konteksti käyttöön.

Tätä mallia käytetään tämän raportin transaktio­esimerkissä myöhemmin.

Page 28: ASPEKTISUUNTAUTUNUT€OHJELMOINTI€€JA … · Luvussa€1€esitellään€aspektisuuntautuneen€ohjelmointitavan€historiaa€ja€käsitteistöä. Luvussa€2€esitellään€AspectJkieli,€joka€toteuttaa€aspektisuuntautuneen€ohjelmoinnin

28

Madonreikämallin kaava:

public aspect WormholeAspect {

   pointcut callerSpace(<caller context>)

: <caller pointcut>;

   pointcut calleeSpace(<callee context>)

: <callee pointcut>;

   pointcut wormhole(<caller context>,

      <callee context>)

: <cflow(callerSpace(<caller context>))

  && <calleeSpace(<callee context>);

// advices to wormhole

around (<caller context>, <callee context>)

  : wormhole(<caller context>, <callee context>){

… advice body

}

}

Seuraava AccountTransactionAspect  ­aspekti  on  yksinkertainen  esimerkki  tä­

män mallin käytöstä. Aspekti luo madonreiän transaktion osapuolten kuten tilinhaltijan,

kassanhoitajan tai verkkopankin ja todellisten operaatioiden välille. AccountTransactio­

nAspect.java:

Page 29: ASPEKTISUUNTAUTUNUT€OHJELMOINTI€€JA … · Luvussa€1€esitellään€aspektisuuntautuneen€ohjelmointitavan€historiaa€ja€käsitteistöä. Luvussa€2€esitellään€AspectJkieli,€joka€toteuttaa€aspektisuuntautuneen€ohjelmoinnin

29

public aspect AccountTransactionAspect {

// 1. transaktiojärjestelmän operaatioiden käyttö

  pointcut transactionSystemUsage(TransactionSystem ts)

       : execution(*TransactionSystem.*(..))&&this(ts);

// 2. tilioperaatioiden käyttö

  pointcut accountTransactions (Account account,

                                float amount)

       : this(account) && args(amount)

        && (execution(public * Account.credit(float))

        || (execution(public * Account.debit(float)));

// 3. luo madonreiän kohtien 1 ja 2 välille

   pointcut wormhole (TransactionSystem ts,

              Account account,  float amount)

       : cflow(transactionSystemUsage (ts))

        && accountTransactions (account, amount);

// 4. käyttää madonreiän mahdollistamaa kontekstia

before (TransactionSystem ts,

              Account account,  float amount) returning

        : wormhole(ts, account, amount)  {

// esim. kirjoitetaan loki transaktion operaatioiden

// etenemisestä, authorisoinnista jne.

}}  // AccountTransactionAspect.java päättyy

Page 30: ASPEKTISUUNTAUTUNUT€OHJELMOINTI€€JA … · Luvussa€1€esitellään€aspektisuuntautuneen€ohjelmointitavan€historiaa€ja€käsitteistöä. Luvussa€2€esitellään€AspectJkieli,€joka€toteuttaa€aspektisuuntautuneen€ohjelmoinnin

30

Kohtien selitykset:

Kohta 1: transactionSystemUsage()­poincut  sieppaa kaikki  suoritettavat  join

point  ­kohdat TransactionSystem­objektiin.  Näin  poincut  voi  kerätä  transaktion

kontekstin ja säilyttää sen tässä objektissa.

Kohta 2: accountTransaction()­pointcut sieppaa Account ­luokan credit()­

ja debit()  ­metodien suorituksen. Tämä pointcut säilyttää tiliä  ja summaa koskevan

kontekstin.

Kohta 3: wormhole() ­pointcut luo madonreiän transaktiojärjestelmän operaatioiden

ja tililuokan operaatioiden välille sieppaamalla kaikki ne join point –määrittelyt kohdas­

ta  2  jotka  tapahtuvat transactionSystemUsage() kontrollivirrassa.  Näin

wormhole() ­pointcut asettaa saataville kohdissa 1 ja 2 siepatun kontekstin.

Kohta 4: before advice voi nyt käyttää kontekstia, jonka wormhole()tarjoaa. Tä­

mä advice voi tunnistaa tilin, summan, sekä tilinkäytöstä vastuussa olevan transaktiojär­

jestelmän.

3.3 Poikkeuksien käsittely

AspectJ­kielinen advice ei  voi  heittää  tarkistettua poikkeusta, elleivät  sen  join point –

kohdat voi heittää samaa poikkeusta. Tarkistettu poikkeus laajentaa suoraan tai epäsuo­

rasti Exception –luokan, sen sijaan että laajentaisi RuntimeException –luokan.

Usein kuitenkin järjestelmän tehtävien koostaminen (weaving) vaatii, että aspekti käsit­

telee tarkistettuja poikkeuksia. Esimerkiksi JDBC tietokantayhteyksissä tai JAAS auten­

tikoinnissa aspektit voivat käyttää yleisiä ohjelmakirjastoja  ja palveluja. Näistä heitetyt

poikkeukset ovat yleensä tarkistettuja poikkeuksia, joita alusta pystyy käsittelemään.

Page 31: ASPEKTISUUNTAUTUNUT€OHJELMOINTI€€JA … · Luvussa€1€esitellään€aspektisuuntautuneen€ohjelmointitavan€historiaa€ja€käsitteistöä. Luvussa€2€esitellään€AspectJkieli,€joka€toteuttaa€aspektisuuntautuneen€ohjelmoinnin

31

Lisäksi  tietyn  tyyppiset  poikkileikkaukselliset  tehtävät,  kuten  virheistä  toipuminen  ja

transaktionhallinta vaativat, että aspekti sieppaa kaikentyyppiset poikkeukset joita suori­

tettavat  joint point –kohdat heittävät. Näitä varten aspektin catch­lohkoon on määritel­

tävä poikkeuksen käsittelyn logiikka. Tilannetta hankaloittaa vielä se, että aspektit ovat

uudelleenkäytettäviä, eivätkä ne osaa käsitellä liiketoimintakohtaisia poikkeuksia.

Poikkeuksien käsittely ­malli perustuu siihen, että suorituslogiikassa syntyvä alkuperäi­

nen, tarkistettu poikkeus poimitaan ja heitetään uusi ajonaikainen poikkeus,  joka käärii

alkuperäisen poikkeuksen. Kun ajonaikainen poikkeus tapahtuu, siitä  ilmoitetaan poik­

keuksena ylemmän tason kutsujalle. Sen on myös voitava käsitellä poikkeus, vaikka se

ei olisi tietoinen järjestelmän aspektien  määrittelyistä.

Mallin mukaisesti voi käsitellä liiketoimintakohtaisia poikkeuksia uudelleenkäytettävis­

sä aspekteissa. Toisin sanoen on luotava tehtäväkohtainen (concern­specific) ajonaikai­

nen poikkeus, joka voi asettaa tarkistetun poikkeuksen aiheuttajakseen. Asettamisen voi

tehdä  joko välittämällä poimitun poikkeuksen  ajonaikaisenpoikkeuksen konstruktorille

tai käyttämällä Exception­luokan initCause() –metodia. Esimerkiksi implementoi­

taessa pysyvyysaspektia JDBC:tä käyttäen, voi heittää PersistenceRuntimeExcep­

tion ­poikkeuksen, joka käärii alkuperäisen tarkistetun SQLException ­poikkeuksen.

3.3.1 Tehtäväkohtaisen poikkeuksen käsittely aspektissa

Esimerkkinä liitteen 2A ConcernAspect –aspekti toteuttaa poikkeuksen käsittelykaa­

van.  Kaava  esittää  mallin,  jossa  tehtäväkohtainen ConcernCheckedException  –

tyyppinen poikkeus siepataan ja kääritään ConcernRuntimeException –tyyppiseksi

poikkeukseksi. Tämä säilyttää alkuperäisen poikkeuksen niin, että sen vastaanottaja voi

nähdä alkuperäisen poikkeuksen tyypin. Mallia käytettäessä sen käsitteiden nimet kor­

vataan tehtäväkohtaisilla käsitteillä.

Aspektissa  käytetään ConcernRuntimeException­luokkaa, jonka  konstruktori

saa  alkuperäisen  heitetyn  poikkeuksen  parametrikseen.  Tästä  parametristä  ilmenee

Page 32: ASPEKTISUUNTAUTUNUT€OHJELMOINTI€€JA … · Luvussa€1€esitellään€aspektisuuntautuneen€ohjelmointitavan€historiaa€ja€käsitteistöä. Luvussa€2€esitellään€AspectJkieli,€joka€toteuttaa€aspektisuuntautuneen€ohjelmoinnin

32

poikkeuksen syy, mikäli kutsuja tarvitsee sitä. Aspektin before advice sieppaa alkupe­

räisen  tarkistetun  poikkeuksen,  käärii  sen  tarkistamattomaksi  poikkeukseksi  ja  heittää

sen. Tässä advice saa  alkuperäisen poikkeuksen void concernLogic() –metodilta.

ConcernAspect­aspektin ja mallin muu lähdekoodi on testausluokkineen liitteessä 2A.

3.3.2 Liiketoimintokohtaisen poikkeuksen käsittely aspektissa

Samaa poikkeuksen esittely –mallia voi käyttää tehtäväkohtaisten tarkistettujen poikke­

usten  lisäksi  myös  liiketoimintokohtaisten  tarkistettujen  poikkeusten  käsittelyyn.  Jois­

sain tilanteissa jonkin aspektin advice­lohkon on kyettävä poimimaan kaikki poikkeuk­

set. Tällöin aspektin  pitää pystyä heittämään edelleen liiketoimintokohtaisia poikkeuk­

sia eli kun poikkeus on siepattu, sitä pitää pystyä käsittelemään jollain tavoin.

 Edellä esitettyä ConcernAspect –aspektia  voidaan  muuttaa niin,  että se ottaa kiinni

kaikki poikkeukset,  jotka sen pointcut  sieppaa.  Lisätään aspektiin around advice,  joka

käsittelee  siepatut  operaatiot  try/catch­lohkossa.  Kun  catch­lohko  on  suoritetaan,  se

muodostaa  tehtäväkohtaisen  virheenkäsittelyn  ja  heittää  kutsujalle  uuden Concern­

RuntimeException –tyyppisen poikkeuksen, joka on kääre alkuperäiselle tarkistetulle

poikkeukselle. Muutettu ConcernAspect­aspektin ja mallin muu lähdekoodi on testaus­

luokkineen liitteessä 2B.

3.3.3 Poikkeuksen taltiointi aspektissa

Liiketoimintometodien suoritukseen tarvitaan liiketoimintakohtaisten poikkeusten käsit­

telyä. Kun kaikki poikkeukset siepataan ja kääritään ajonaikaisiksi poikkeuksiksi,   kut­

sujan on saatava käyttöönsä poikkeuksen todellinen syy,  jotta sitä voidaan käyttää   to­

teutettavan sovelluksen  tarpeiden  mukaan. Siepatusta poikkeuksesta syy voidaan ottaa

talteen ja lähettää se edelleen kutsujalle.

Page 33: ASPEKTISUUNTAUTUNUT€OHJELMOINTI€€JA … · Luvussa€1€esitellään€aspektisuuntautuneen€ohjelmointitavan€historiaa€ja€käsitteistöä. Luvussa€2€esitellään€AspectJkieli,€joka€toteuttaa€aspektisuuntautuneen€ohjelmoinnin

33

Edellisen  kappaleen  esimerkkiin  voidaan  lisätä PreserveBusinesException  –

aspekti,  joka  ottaa  talteen  ajonaikaisen poikkeuksen  syyn.  Tämä  aspekti  ei  ole  uudel­

leenkäytettävä  vaan  se  on  toteutettava  järjestelmäkohtaisesti.  Aspektin  lähdekoodi  on

käyttöesimerkkeineen liitteessä 2C.

PreserveBusinessException­aspektin  toiminta:  kun  jokin  metodi  ­  joka  pystyy

heittämään  liiketoimintakohtaisen  poikkeuksen  ­  on  heittänyt ConcernRuntimeEx­

ception­tyyppisen  poikkeuksen,    kutsutaan PreserveBusinessException­

aspektissa after advice,  joka voi myös heittää  liiketoimintakohtaisen poikkeuksen. Ad­

vice­määrittelyn rungossa tarkistetaan onko ajonaikaisen poikkeuksen aiheuttaja sellai­

nen  liiketoimintapoikkeus  joka  pitäisi  säilyttää.  Jos  on,  sen  tyyppi    pakotetaan Bu­

sinessException  –tyypiksi    ja  poikkeuksen  syy  heitetään  edelleen  kutsujal­

le.PreserveBusinessException­aspektin lähdekoodi on liitteessä 2 C.

3.4 Osallistuja­suunnittelumalli

Monilla järjestelmän operaatioilla on yhteisiä erityispiirteitä, kuten yksinkertaiset trans­

aktio­ominaisuudet,  methodin  kutsujen  ajallinen  kesto,  IO­toiminnon  ominaisuudet,

etäkäytön  ominaisuudet,  tai  muu  ominaisuus  jonka  perusteella  jotkin  operaatiot  ovat

osallisena johonkin järjestelmään laajalti vaikuttavaan tehtävään. Koska nämä operaati­

ot  ovat  hajotettuna    useissa  moduuleissa,  operaatioiden  käytöksen  laajentaminen  ja

muuttaminen  on  poikkileikkauksellinen  tehtävä.  Osallistuja­suunnittelumalli  tarjoaa

erään tavan modularisoida tällaista erityistuntomerkkeihin pohjautuvaa poikkileikkauk­

sellista tehtävää. Malli auttaa sieppaamaan join point –kohdat erityispiirteiden perusteel­

la silloin kun nimeen perustuva sieppaus ei riitä.

Kun halutaan hallita järjestelmän hitaita operaatioita ja niiden aiheuttamaa odotusaikaa,

voidaan näitä operaatioita suorittavia metodeja hakea metodien nimeen (signature) pe­

rustuvilla  pointcut  –määrittelyillä.    Esimerkiksi  kun  metodi  heittää IOException  –

poikkeuksen, voidaan päätellä että se suorittaa hitaan IO­operaation. Näin voidaan tun­

Page 34: ASPEKTISUUNTAUTUNUT€OHJELMOINTI€€JA … · Luvussa€1€esitellään€aspektisuuntautuneen€ohjelmointitavan€historiaa€ja€käsitteistöä. Luvussa€2€esitellään€AspectJkieli,€joka€toteuttaa€aspektisuuntautuneen€ohjelmoinnin

34

nistaa joitain hitaita metodeja. Myös metodin nimestä voidaan päätellä sen ominaisuuk­

sia. Esimerkiksi kun nimi on set ­alkuinen, kyseessä on todennäköisesti tilaan vaikut­

tava operaatio. Näin ei kuitenkaan voida määritellä kaikkien operaatioiden erityistunto­

merkkejä.  Operaatiohan  voi  olla  esimerkiksi  hidas,  koska  se  suorittaa  monimutkaisia

laskutoimituksia,  eikä  metodin  nimi  paljasta  sen  ominaisuuksia.  Siksi  ominaisuuksiin

perustuvaa pointcut­määrittelyä ei    voida koostaa  reflektoimalla  jokerimerkeillä  (wild­

cards).

Jotta  tällaiset  erityispiirteitä  omaavat  join  point  –kohdat  voidaan  siepata  pointcut­

määrittelyyn,  tarvitaan  niitä  toteutettavien  luokkien  yhteistyötä.  Eräs  mahdollisuus  on

täydentää implementointia metadatalla, joka ilmaisee erityispiirteet silloin kun se ei ole

johdettavissa  nimeämiskäytännöstä.  Tätä  ei  kuitenkaan  voida  käyttää  vielä  AspectJ­

kielisessä toteutuksessa.

AspectJ­toteutuksessa Osallistuja­suunnittelumalli  (The  Participant  pattern)  auttaa

sieppaamaan metodit niiden erityispiirteiden perusteella. Malli kuitenkin vaatii ydinto­

teutuksen  modifiointia,  joten  on  mahdollista  että osa muutoksia  tarvitsevista  operaati­

oista  jää  tunnistamatta. Siksi usein on  turvallisempaa käyttää vakiintuneita  nimeen  tai

ominaisuuteen perustuvia pointcut­määrittelyjä.

Osallistuja­suunnittelumallissa  ohjelmaluokkien  sisältämä  poincut  viittaa  edelleen  joi­

hinkin  erityispiirteisiin.  Sen  sijaan  että  poincut­määritelmä  sisällytettäisiin  kuhunkin

luokkaan  ja käytettäisiin  aspektien  advice­lohkossa,  luokkiin  itseensä  määritellään ali­

aspekti (subaspect). Tämä aliaspekti  laajentaa ohjeistavaa aspektia (advising aspect)  ja

sisältää  pointcut­määritelmän.  Tavallaan  tämä  määritelmä  kääntää  aspektin  ja  luokan

roolit päinvastaisiksi. Sen sijaan että tehtäisiin aspektit tietoisiksi luokista ja metodeista,

nyt tehdään luokat tietoisiksi aspekteista.

Malli  rakentuu  seuraavasti. Ensin kirjoitetaan abstrakti  aspekti,  joka sisältää yhden  tai

useampia  abstrakteja  pointcut­määrittelyjä,  jotka  viittaavat  haluttuja  erityispiirteitä

omaaviin  join  point  –kohtiin.  Nämä pointcut­määrittelyt  muodostavat  eräänlaisen  ’as­

pektuaalisen  rajapinnan’.  Aspektin  advice­lohkossa  jokaista  pointcut­määrittelyä  –tai

Page 35: ASPEKTISUUNTAUTUNUT€OHJELMOINTI€€JA … · Luvussa€1€esitellään€aspektisuuntautuneen€ohjelmointitavan€historiaa€ja€käsitteistöä. Luvussa€2€esitellään€AspectJkieli,€joka€toteuttaa€aspektisuuntautuneen€ohjelmoinnin

35

niiden  kompinaatioita  ­    ohjeistetaan  käyttäytymään    halutulla  tavalla.  Tätä  aspektia

voidaan pitää kutsuvana aspektina  (inviting aspect),  jonka kutsuu muita osallistumaan

advice­lohkossaan. Kutsu voi olla pelkkä yksittäinen kutsu, tai se voi sisältää valinnaisia

ehtoja.

Jokaisen  luokan,  jota  halutaan  käyttää  osallistujana,  pitää  sisältää  konkreettinen  alias­

pekti,  joka laajentaa kutsuvaa aspektia. Tämä aliaspekti toteuttaa luokassaan abstraktin

pointcut­määrittelyn  konkreettisesti.    On  huomattava  että  konkreettisen  aliaspektin  ei

tarvitse olla luokan sisäaspekti, vaan se voi olla esimerkiksi vertaisaspekti (peer aspect).

Aliaspekti  on  määriteltävä  jokaiseen  luokkaan,  jota  halutaan  käyttää  osallistujana  yh­

teistyössä.  Kuva  5  esittää  Osallistuja  suunnittelumallin  tyypillistä  rakennetta  UML­

kaaviona.

<<aspect>>AbstractDesiredCharacteristicAspect

+pointcut desiredCharacteristicJoinPoints()

<<aspect>>MyClass1.DesiredCharacteristicParticipant

+pointcut desiredCharacteristicJointPoints()

<<aspect>>MyClass2.DesiredCharacteristicParticipant

+pointcut desiredCharacteristicJoinPoints()

MyClass1

MyClass2

sieppaa piirteet

sieppaa piirteet

Kuva 5. Osallistuja­suunnittelumallin esimerkki UML notaationa

Page 36: ASPEKTISUUNTAUTUNUT€OHJELMOINTI€€JA … · Luvussa€1€esitellään€aspektisuuntautuneen€ohjelmointitavan€historiaa€ja€käsitteistöä. Luvussa€2€esitellään€AspectJkieli,€joka€toteuttaa€aspektisuuntautuneen€ohjelmoinnin

36

3.4.1 Osallistuja­suunnittelumallin kaava

Seuraava mallin kaava (template) sisältää abstraktin aspektin sekä kaksi luokkaa, joissa

on  sisäaspekti.  Näissä    sisäaspekteissa  toteutetaan  abstrakti  pointcut­määrittely  konk­

reettisesti.

AbstractDesiredCharcteristicAspect.java  perustaa  yhteistyön.  Mallissa  on  käytetty

around advice ­määrittelyä, yhtä hyvin voi olla myös before­ tai after advice.

abstract aspect AbstractDesiredCharcteristicAspect {

  public abstract pointcut desiredCharacteristicJoinPoints();

Object around() : desiredCharacteristicJoinPoints() {

// tähän advice koodi

}

}

Haluttu poikkileikkauksellinen käytös kirjoitetaan around advice ­lohkossa, joka määrit­

telelee abstraktin pointcut ­esittelyn.

MyClass1.java on osapuolena yhteistyössä. Luokkaan pitää määritellä sisäaspekti,  joka

on AbstractDesiredCharcteristicAspect­perusaspektin  aliaspekti.  Abstrakti

desiredCharacteristicJoinPoints  ­pointcut  toteutetaan  tässä  MyClass­

luokassa.  Aliaspekti  julistaa,  että  tämän  luokan  metodeilla  haluttuja  piirteitä,  joten  ne

voivat olla osapuolena perusaspektin tarjoamassa yhteistyössä.

public class MyClass1 {

// MyClass1­luokan koodi

public static aspect DesiredCharacteristicParticipant

extends AbstractDesiredCharcteristicAspect {

        public pointcut desiredCharacteristicJoinPoints() :

call(* MyClass1. desiredCharacteristicMethod1())

|| call(* MyClass1. desiredCharacteristicMethod2())

Page 37: ASPEKTISUUNTAUTUNUT€OHJELMOINTI€€JA … · Luvussa€1€esitellään€aspektisuuntautuneen€ohjelmointitavan€historiaa€ja€käsitteistöä. Luvussa€2€esitellään€AspectJkieli,€joka€toteuttaa€aspektisuuntautuneen€ohjelmoinnin

37

/* || jne...*/;

}}

Samaan tapaan voidaan määritellä muita yhteistyöhön osallistuvia luokkia. Osallistuja­

mallissa luokat voidaan täsmällisesti määritellä poikkileikkauksellisen tehtävän toteutta­

jiksi  yhteistyön  osapuolina.  Samoin  on  mahdollista  määritellä  osapuoleksi  luokka­

hierarkia tai pakkaus. Silloin aliaspekti on määritelty luokan ulkopuolelle,  ja tässä osa­

puolen aliaspektissa on pointcut­lohkossa ylläpidettävä listaa tarvittavista halutunpiirtei­

sistä metodeista. Listan toteutus voi perustua myös metodien nimen mukaiseen reflek­

tiiviseen valintaan.

Page 38: ASPEKTISUUNTAUTUNUT€OHJELMOINTI€€JA … · Luvussa€1€esitellään€aspektisuuntautuneen€ohjelmointitavan€historiaa€ja€käsitteistöä. Luvussa€2€esitellään€AspectJkieli,€joka€toteuttaa€aspektisuuntautuneen€ohjelmoinnin

38

4 SÄIETURVALLISUUS

Säieturvallisuus  vaatii  järjestelmän  oikean  käyttäytymisen  ylläpitoa  tilanteessa,  jolloin

järjestelmässä useat säikeet käyttävät sen tilaa. Koska säikeet vaikuttavat eri osissa so­

vellusta, niiden toteutus, muuttaminen ja testaus voi aiheuttaa ongelmia. Mikäli tässä ei

onnistuta, järjestelmässä esiintyy käyttöliittymätasolla epämääräistä tulostumista, datan

eheys on puutteellista ja järjestelmä voi hidastella tai lukittua kokonaan.

Näihin  ongelmiin on  käytettävissä  ratkaisumalleja.  Niissä  määritellään objektien  luki­

tuksia  jotta  vältyttäisiin  järjestelmän  lukkiutumiselta  ja  pyritään  tehokkaaseen  mo­

niajoon  sekä  välttämään  ylikuormitus.  Jokainen  ongelma  on  kuitenkin  analysoitava

erikseen, jotta voidaan valita oikea ratkaisumalli.

Tässä  raportissa  esitetään  kaksi  AspectJ­kielistä  ratkaisua.  Swing­toteutuksen  mallissa

pyynnöt välitetään suojatuille objekteille määrätyssä säikeessä. Toisessa mallissa käyte­

tään lukemisen ja kirjoittamisen lukitusta (read­write lock pattern).

4.1 Swing ja yhden säikeen sääntö

Swing,  joka on hyvin yleinen Javan GUI ­kirjasto, käyttää yhden säikeen turvallisuus­

sääntöä. Se vaatii, että kaikkien Swing­komponenttien on käytettävä vain yhtä tapahtu­

masäiettä (event­dispatching thread). Rajoittamalla käytön vain yhteen määrättyyn säi­

keeseen, malli siirtää turvallisuus ongelmat pois komponentin toteutuksesta. Kun toinen

säie  tarvitsee  Swing­komponentin  palveluja,  sen  pitää  pyytää  tapahtumasäiettä  suorit­

tamaan operaatio, koska ainoastaan tapahtumasäie saa päivittää näkyviä komponentteja.

Yksinkertaisissa  sovelluksissa,  joissa ei ole käyttäjän  luomia  säikeitä,  tämä  sääntö toi­

mii  hyvin.  Monimutkaisissa  sovelluksissa,  joissa taustasäikeet  (nonevent­dispatching

thread)  käyttävät UI­komponentteja,  sääntö on kuitenkin rajoittava  tekijä. Esimerkiksi

tilanne, jossa tapahtumasäie suorittaa verkkoon tai IO­keskeytyksiin liittyviä operaatioi­

ta  tai  tietokantatoimintoja,  ja  taustasäikeen  pitäisi  pystyä  päivittämään  käyttöliittymää

palvelimen  informaatiolla. Kun palvelimelle  lähetetään pyyntö,  jonka perusteella käyt­

Page 39: ASPEKTISUUNTAUTUNUT€OHJELMOINTI€€JA … · Luvussa€1€esitellään€aspektisuuntautuneen€ohjelmointitavan€historiaa€ja€käsitteistöä. Luvussa€2€esitellään€AspectJkieli,€joka€toteuttaa€aspektisuuntautuneen€ohjelmoinnin

39

töliittymä  päivitetään,  tapahtumasäie  ei  voi  jäädä  odottamaan  vastausta,  koska  tällöin

koko käyttöliittymä lukittuu kunnes palvelin vastaa.   Jotta näin ei kävisi,  jonkun toisen

säikeen on odotettava, jotta käyttöliittymää voidaan päivittää. Toisaalta päivitystä ei voi

jättää taustasäikeen tehtäväksi, koska näyttö jää epämääräiseen tilaan.

Ratkaisuksi  tähän  ongelmaan  Swing  sallii  tapahtumasäikeen  käyttämisen  muiden  säi­

keiden pyyntöjen välittämiseen. Säikeiltä voi  jättää operaation suorituspyyntöjä  tapah­

tumasäikeelle  käyttämällä EventQueue.invokeLater()  tai Event­

Queue.invokeAndWait()­kutsuja. Molemmissa välitetään Runnable –objekti,  jon­

ka run()  –metodi  suorittaa  aiotun  operaation.  Tässä  ratkaisun  hankaluudeksi  tulee

Runnable  –luokkan  laajennusluokkien  kirjoittaminen  jokaista  ei­AWT­säikeestä  kut­

suttavaa metodia varten, sekä näiden luokkien käyttäminen suorien kutsujen sijaan. On

myös varmistettava  luokan on yhdessä EventQueue  ­luokan kanssa korvattava kaikki

ei­AWT­säikeestä tulevat kutsut.

4.1.1 Perinteinen ratkaisu

Liitteessä  3 Test­luokan  lähdekoodi  esittää  säieturvallisuuden  perinteisen  ratkaisun.

Test­luokka  toteuttaa  käyttöliittymän ikkunan  (frame).  Tällöin  yhden  säikeen  sääntö

astuu voimaan.

Tämän  jälkeen  tehdyt  metodin kutsut  kääritään anonyymeihin Runnable –luokan  il­

mentymiin. Tämän  luokan run() –metodi kutsuu suoritettavia  metodeja.  Anonyymin

luokkan sijaan voisi yhtä hyvin käyttää nimettyjä luokkia. Ensimmäinen metodi tulostaa

ikkunaan  pienen  taulukon.  Metodi  suoritetaan  asynkronisesti,  joten  sille  kutsutaan

EventQueue.invokeLater()­metodia.  Toinen  metodi  tulostaa  OK­

viestipainikkeen. Tämä metodi suoritetaan asynkronisesti, joten sille kutsutaan Event­

Queue.invokeAndWait()­metodia.

Seuraavaksi  välitetään  reititysluokan  (Runnable)  ilmentymä. invokeLater()­

metodia  käytetään  jos  kutsu  pitää  suorittaa  jumiuttamatta  kutsujaa. invokeAnd­

Page 40: ASPEKTISUUNTAUTUNUT€OHJELMOINTI€€JA … · Luvussa€1€esitellään€aspektisuuntautuneen€ohjelmointitavan€historiaa€ja€käsitteistöä. Luvussa€2€esitellään€AspectJkieli,€joka€toteuttaa€aspektisuuntautuneen€ohjelmoinnin

40

Wait()­metodia  käytetään  silloin,  kun  kutsujan  pitää  jäädä  odottamaan  operaation

suoritusta.

Test­luokan kohtien selitykset:

Kohta  1:  Tällä  kohtaa  käyttöliittymä  toteutetaan  eli  kehys  näkyy  kuvaruudulla.  Taus­

tasäikeitä voi kutsua vielä ennen tätä kohtaa, koska AWT­säie ei käytä komponentteja.

Pääsäie on ainoa säie, joka päivittää käyttöliittymäkomponentin tilaa.

Kun käyttöliittymä on toteutettu, AWT­säie lukee ja päivittää sovelluksen tilaa ja koska

Swing­luokat  eivät  tarjoa  mitään  poissulkevaa käytön  suojausta,  on  pyydettävä  tapah­

tumasäiettä  suorittamaan  operaatio  kutsuvan  säikeen  puolesta.  Näin  taataan,  että  vain

tapahtumasäie hallitsee käyttöliittymän komponentteja.

Kohta  2:  Pyyntö  taulukon  kentän  arvon  asettamisesta  voidaan  tehdä  asynkronisesti,

koska ei ole vaatimusta siitä milloin tämä operaatio on suoritettu loppuun. Ensin pyyntö

kääritään Runnable­luokan  toteuttavaan  anonyymiin  luokkaan,  jonka run()  –

metodissa alkuperäinen operaatio jatkuu. Tässä  joudutaan antamaan paikallisille muut­

tujille final  –määre,  koska  paikallissa  luokissa  käytetyille  muuttujille  Java  pakottaa

antamaan tämän määreen.

Koska  operaatioille  ei  ole  vaadittu  synkronista  suoritusta,  käytetään Event­

Queue.invokeLater()  ­metodia  lähettämään  pyyntö  operaatioiden  suorituksesta

asynkronisesti. Nämä pyynnöt menevät tapahtumankäsittelyjonoon, josta tapahtumasäie

poimii pyyntöobjektit ja kutsuu run()­metodia, joka suorittaa operaatiot.

Kohta 3: JoptionPane.showMessageDialog()­metodin kutsu suoritetaan synk­

ronisesti kutsujan kanssa. Kutsuja ei voi edetä seuraavaan operaatioon ennenkuin kutsu

on suoritettu, koska kyseessä on toimenpide, joka odottaa ilmoituksen kuittaamista.

Mikäli  operaation  pitää  jäädä  odottamaan,  käytetään Event­

Queue.invokeAndWait()­metodia pyynnön lähettämiseen. Pyyntö laitetaan tapah­

tumankäsittelyjonoon ja kutsuja  jää odottamaan pyyntöobjektin suorittamista, kun se on

Page 41: ASPEKTISUUNTAUTUNUT€OHJELMOINTI€€JA … · Luvussa€1€esitellään€aspektisuuntautuneen€ohjelmointitavan€historiaa€ja€käsitteistöä. Luvussa€2€esitellään€AspectJkieli,€joka€toteuttaa€aspektisuuntautuneen€ohjelmoinnin

41

suoritettu kutsuja  vapautetaan. Tämän Test­luokan  suorituksessa käyttäjä  joutuu pai­

namaan OK­nappulaa, ennenkuin suoritus jatkuu.

Kohta  4:  Kun getRowCount()­metodin  kutsulta  odotetaan  paluuarvoa,  operaation

pitää toimia synkronisesti kutsujan kanssa, koska seuraava operaatio voi riippua paluu­

arvosta. Koska paikallisissa luokissa käytetyt muuttujat ovat final­määreisiä, ei get­

RowCount()­metodista  saatua  paluuarvoa  voida  sijoittaa rowCount­muuttujaan.

Paluuarvo otetaan talteen luomalla uusi final­määreinen integer­taulukko, sijoitetaan

paluuarvo  taulukon  elementiksi  ja  lopulta  asetetaan  tämä  elementti rowCount­

muuttujan arvoksi. Jos Test­luokassa olisi käytetty nimettyjä luokkia, olisi niihin voi­

nut lisätä jäseniä paluuarvoa varten.

Kohta  5:  Kutsu getGridColor()­metodille  on  yhtäläinen getRowCount()­

metodin kanssa, paitsi että paluuarvo saadaan objektina.

Poikkeuksia ei ole käsitelty Test­luokassa, jotta esimerkistä ei tulisi pitkä. Liitteessä 3

on LogUIAspect­aspekti  lähdekoodi,  jolla  voi  kirjoittaa  lokin Test­luokan  toimin­

nasta.

LogUIAspect­aspekti kirjoittaa lokin kaikista metodien kutsuista luokissa, jotka ovat

javax –pakkauksessa  ja sen alipakkauksissa. Aspektin before advice kirjoittaa metodin

sijainnin  ja  nimen  (signaturen)  ja Thread.currentThread()­metodia  käyttävän

kutsuvan säikeen nimen.

4.1.2 Säieturvallisuus aspektina

Tässä kappaleessa esitetään AspectJ­kielinen säieturvallisuuden ratkaisu, joka noudattaa

yhden  säikeen  sääntöä.  Ratkaisussa  sovelletaan  Worker­objektin  luonti  –

suunnittelumallia.  Käyttöliittymää  päivittävät  metodit  siepataan  ja  suunnittelumallin

mukaisesti  luodaan Runnable­objekti. Tarkistetaan onko kutsuva  säie  jo  tapahtuma­

jonossa. Jos se on jonossa, annetaan alkuperäisen metodin suorittaa operaatio, jos se ei

ole jonossa Worker­objekti laitetaan tapahtumajonoon odottamaan suoritusta.

Page 42: ASPEKTISUUNTAUTUNUT€OHJELMOINTI€€JA … · Luvussa€1€esitellään€aspektisuuntautuneen€ohjelmointitavan€historiaa€ja€käsitteistöä. Luvussa€2€esitellään€AspectJkieli,€joka€toteuttaa€aspektisuuntautuneen€ohjelmoinnin

42

Tässä  aspekti­ratkaisussa  toteutetaan  Swingin  yhdensäikeen  sääntö,  jolloin  säikeiden

käsittelyä  ei  tarvitse  toteuttaa Test­luokassa,  kuten  perinteisessä  ratkaisussa  tehtiin.

Aspekti reitittää tapahtumasäikeen kautta ne metodien kutsut, jotka käyttävät tai muut­

tavat Swing­komponenttien tilaa. Tämän aspektin yhteydessä edellä esitettyä LogUIAc­

tivitesAspect­aspektia voi käyttää UI­operaatioiden lokin kirjoittamiseen.

Ratkaisussa esitetään abstrakti aspekti,  josta implementoidaan konkreettinen aliaspekti,

joten ratkaisua voi soveltaa erilaisiin järjestelmiin aliaspektia muuttamalla.

Liitteessä  4  on  esitetty  abstraktin SwingThreadSafetyAspect­aspektin,    konk­

reettisen DefaultSwingThreadSafetyAspect­aliaspektin  sekä ratkaisua testaa­

van Test­luokan lähdekoodi.

SwingThreadSafetyAspect­aspektin  abstrakti uiMethodCalls­pointcut  siep­

paa käyttöliittymän metodien kutsut. Pointcut määritellään konkreettisessa DefaultS­

wingThreadSafetyAspect­aliaspektissa.

SwingThreadSafetyAspect­aspektin  abstrakti uiSyncMethodsCalls­

pointcut sieppaa synkronista suoritusta tarvitsevat metodit. Pointcut määritellään konk­

reettisessa DefaultSwingThreadSafetyAspect ­aliaspektissa.

SwingThreadSafetyAspect­aspektin threadSafeCalls­pointcut  luettelee

ne  metodien  kutsut,  joiden  ei  tarvitse  noudattaa yhden  säikeen  sääntöä.  Näitä  kutsuja

ovat JComponent.revalidate(), JComponent.repaint() sekä  kuunteli­

joiden lisääminen ja poistaminen.

SwingThreadSafetyAspect­aspektin excludedJoinpoints ­pointcut

lohkossa  valitaan  metodien  kutsut.  Lohkossa  poissuljetaan threadSafeCalls()­

poincut  lohkon sieppaamat aspektin  join point­kohdat  sekä ne  jotka suoritetaan  tapah­

tumasäikeessä.  Ehto if(EventQueue.isDispatchhThread()) saa  totuusar­

von true, vain jos tämänhetkinen suoritettava säie on tapahtumasäie.

Page 43: ASPEKTISUUNTAUTUNUT€OHJELMOINTI€€JA … · Luvussa€1€esitellään€aspektisuuntautuneen€ohjelmointitavan€historiaa€ja€käsitteistöä. Luvussa€2€esitellään€AspectJkieli,€joka€toteuttaa€aspektisuuntautuneen€ohjelmoinnin

43

SwingThreadSafetyAspect­aspektin routedMethods()  ­poincut  sieppaa  ne

join point –kohdat, jotka tarvitsevat kutsujen reittämistä tapahtumasäikeen kautta.

SwingThreadSafetyAspect­aspektin around  advice  –lohkoissa  varmistetaan

reititystä  tarvitsevien  metodien  suoritus  Worker­objektina  synkronisesti.  Myös void­

metodeille, jotka uiSyncMethodsCalls­pointcut  määrittelee, varmistetaan synkroni­

nen suoritus.

Liitteessä  4  esitetään  myös DefaultSwingThreadSafetyAspect­aliaspekti,

jonka  avulla SwingThreadSafetyAspect­aspekti  kontrolloi  metodien  reititystä.

Aliaspektissa määritellään synkronista reititystä vaativat metodit.

Aliaspektin pointcut­määrittelyjen selitys:

viewMethodCalls()  –pointcut  valitsee  kutsut  UI­komponenttien  metodeille.  Se

sieppaa kaikki JComponent­luokan ja sen aliluokkien metodit.

modelMethodCalls() –pointcut valitsee kaikki UI­malliluokkien ja niiden aliluok­

kien metodeille.

uiMethodCalls() –pointcut valitsee kutsut UI­metodeille yhdistettynä.

uiSyncMethodCalls() ­pointcut valitsee kaikki kutsut JOptionPane­luokan ja sen

aliluokkien metodeille. Ne ovat synkronista suoritusta vaativia UI­metodeja.

4.1.3 Objektin lukitusmalli aspektina

Kilpailevien  säikeiden  luku­  ja  kirjoitusoperaatioiden  kohdistuessa  samaan  objektiin

voidaan  sen  eheys  varmistaa  lukintamenettelyllä.  Menettelyn  perusajatuksena  on,  että

objektia voi  lukea, ellei  sen tilaa olla parhaillaan muuttamassa. Perinteisessä  luokkato­

teuksessa  lukitusmekanismi  vaatii  jokaisen  luku­  ja  kirjoitusmetodin  kohdalla  erillistä

koodausta. Seuraavassa esitetään lukitusmalli, johon kuuluu uudelleenkäytettävä perus­

Page 44: ASPEKTISUUNTAUTUNUT€OHJELMOINTI€€JA … · Luvussa€1€esitellään€aspektisuuntautuneen€ohjelmointitavan€historiaa€ja€käsitteistöä. Luvussa€2€esitellään€AspectJkieli,€joka€toteuttaa€aspektisuuntautuneen€ohjelmoinnin

44

aspekti  sekä  sen  aliaspekti,  jota  muokkaamalla  mallia  voidaan  käyttää  eri  sovellusten

luokkien kanssa. Näiden aspektien ja esimerkkiluokkien lähdekoodi on liitteessä 5.

Perusaspekti kapseloi lukitusmekanismin mallin. Aspekti sisältää kaksi pointcut­ määri­

telyä, ensimmäinen sieppaa lukumetodien suoritukset ja toinen kirjoitusmetodien. Nämä

suoritukset voidaan synkronoida.

Liitteen  5 ReadWriteLockSyncronizationAspect­aspekti  käyttää  JSR166­

luokkakirjastoa, joka on noudettavissa verkosta, katso [Lea05]. Luokkakirjasto on kehit­

teillä  ja  täysin  valmistuttuaan  se  tulee  olemaan  käytössä  Javan ja­

va.util.concurrent –pakkauksena.

ReadWriteLockSyncronizationAspect­aspektin selitys kohdittain:

perthis()assosioi aspektin  instanssit niihin Worker­objekteihin,  jotka sopivat  luku­

tai  kirjoitusmetodeihin.  Nämä  on  metodit  luetellaan    konkreettisessa  aspektissa.  Uusi

aspektin  instanssi  luodaan  jokaiselle objektille,  jolle siepattu metodi suoritetaan. Asso­

siaatio mahdollistaa  lukitusobjektin esittelyn kaikille  synkronoiduille  luokille, objektin

tyyppiä ei tarvitse tietää.

Abstrakti readOperations() –pointcut  määritellään  aliaspektissa  sieppaamaan

kaikki  ne  metodit,  jotka  eivät  muuta  objektin  tilaa.  Aliaspektissa  määritellään  myös

abstrakti writeOperations()­pointcut sieppaamaan metodit, jotka muuttavat objek­

tin tilaa.

Lukitusmallissa _lock  –muuttuja  palvelee  syknronoinnin  tukena.  Koska  aspekti  on

assosioitu tarvittavien  join point –kohtien objekteille, _lock –muuttuja on assosioitu

objektien instansseihin.

before():readOperations()  ja after():readOperations() ­advice  loh­

koissa lukitaan ja vapautetaan lukuoperaatiot.

Samoin before:writeOperations()  ja after:writeOperations() ­

advice lohkoissa lukitaan ja vapautetaan kirjoitusoperaatiot.

Page 45: ASPEKTISUUNTAUTUNUT€OHJELMOINTI€€JA … · Luvussa€1€esitellään€aspektisuuntautuneen€ohjelmointitavan€historiaa€ja€käsitteistöä. Luvussa€2€esitellään€AspectJkieli,€joka€toteuttaa€aspektisuuntautuneen€ohjelmoinnin

45

Poikkeusten pehmentäminen konvertoi acquire­metodien kutsujen heittämät Interrup­

tedException –poikkeukset, joten siepattujen operaatioiden API:a ei tarvitse muuttaa.

ReadWriteLockSyncronizationAspect­aspektia  voidaan  käyttää  aliaspektin

kanssa yksittäiselle  luokalle tai koko luokkakirjaston lukitusmallina. Esimerkinä Ban­

kingSynchronizationAspect­aspekti  mahdollistaa  mallin  soveltamisen Ac­

count­luokkaan, myös näiden lähdekoodi on liitteessä 5.

Page 46: ASPEKTISUUNTAUTUNUT€OHJELMOINTI€€JA … · Luvussa€1€esitellään€aspektisuuntautuneen€ohjelmointitavan€historiaa€ja€käsitteistöä. Luvussa€2€esitellään€AspectJkieli,€joka€toteuttaa€aspektisuuntautuneen€ohjelmoinnin

46

5 AUTENTIKOINTI JA AUKTORISOINTI

Autentikointi  (authentication)  on  oikeuksien  tarkistamisprosessi,  jossa  todennetaan

käyttäjän  tunnisteet,  esimerkiksi  käyttäjätunnuksen  ja  salasanan  avulla. Auktorisointi

(authorization) on prosessi,  jossa  tarkistetaan autentikoidun käyttäjän oikeudet käyttää

tarjolla  olevia  resursseja.  Näiden  prosessien  toteuttamiseksi  rakennetut  API:t,  kuten

Java Authentication and Authorization Service (JAAS), mahdollistavat resurssien käytön

valvonnan erottamisen muusta koodista. Näiden ohjelmarajapintojen rinnalle on kehitet­

ty  erilaisia  standardeja  konfiguraation  määrittelykieliä,  kuten  Security  Assertion  Mar­

kup  Language  (SAML)  ja  Extensible  Access  Control  Markup  Language  (XACML).

Näiden API:en ja standardien pyrkimyksenä on ollut vähentää monimutkaisuutta ja tar­

jota nopeita ja toimivia toteutuksia.

Vaikka  näitä  ohjelmointirajapintoja  käytettäisiin,  perinteiset  ohjelmointitavat  vaativat

moduulikohtaista  autentikoinnin  ja  auktorisoinnin  koodaamista.  Esimerkiksi  liiketoi­

mintasovelluksen käyttäjien  oikeuksien valvonnan  toteuttamiseksi  pitää  lisätä  kaikkiin

liiketoimintametodeihin kutsut JAAS­metodeille. Sama koskee myös käytön valvonnan

logiikkaa, koska liiketoimintalogiikka levittäytyy useisiin moduleihin,.

Seuraavassa  kappaleessa  esitellään  yksinkertainen  pankkijärjestelmä.  Tähän  järjestel­

mään lisätään myöhemmin autentikointi ja auktorisointi AspectJ­ratkaisuna.

5.1 Pankkijärjestelmä

Pankkijärjestelmän  ydintoteutus  sisältää  seuraavat  luokat:  pankkitilin  rajapintaluokka

Account.java,  josta  toteutetaan  tililuokka AccountSimplImpl.java,  poikkeuksia

käsittelevä  luokka InsufficientBalanceException.java,    tilinsiirron  toteuttava

luokka InterAccountTransferSystem.java,  sekä  järjestelmän  testaamiseksi

Test.java –luokka. Katso kuva 6.

Page 47: ASPEKTISUUNTAUTUNUT€OHJELMOINTI€€JA … · Luvussa€1€esitellään€aspektisuuntautuneen€ohjelmointitavan€historiaa€ja€käsitteistöä. Luvussa€2€esitellään€AspectJkieli,€joka€toteuttaa€aspektisuuntautuneen€ohjelmoinnin

47

Kuva 6. Pankkijärjestelmän ydintoteutus.

Account­rajapinta esittelee get­metodin tilinumeron saantiin, tilin hyvitys­ ja veloitus­

metodin, sekä get­metodin tilinsaldolle. AccountSimplImpl­luokka toteuttaa tämän

rajapinnan. InterAccountTransferSystem –luokka  sisältää  tilinsiirtometodin.

Kaksi viimemainittua  luokkaa voivat heittää InsufficientBalanceException

–poikkeuksen, mikäli tilin saldo ylittyy.

Ohjelman  metodien  suoritusjärjestyksen  seuraamiseksi  käytetään AuthLog­

ging.java –aspektia,  joka  listaa tili­  ja tilinsiirtoluokan metodien nimet suoritusjär­

jestyksessä.

Test­luokassa luodaan kaksi tiliä, ensimmäistä tiliä hyvitetään kerran ja velotaan ker­

ran, sekä suoritetaan kaksi siirtoa toiselle  tilille,  jolloin ensimmäisen tilin saldo ylittyy

ja ohjelma heittää poikkeuksen.

Page 48: ASPEKTISUUNTAUTUNUT€OHJELMOINTI€€JA … · Luvussa€1€esitellään€aspektisuuntautuneen€ohjelmointitavan€historiaa€ja€käsitteistöä. Luvussa€2€esitellään€AspectJkieli,€joka€toteuttaa€aspektisuuntautuneen€ohjelmoinnin

48

5.2 JAAS­pohjainen autentikointi perinteisellä tavalla

Järjestelmään  voidaan  lisätä  autentikointitoiminnallisuutta,  esimerkiksi autentikointi

tarvittaessa (just­in­time). Silloin autentikointi tapahtuu vasta kun käyttäjä yrittää avata

sellaista järjestelmän toimintoa, joka vaatii käyttäjän identiteetin todentamisen. Pelkässä

sisäänkirjautumisen autentikoinnissa  (upfront  login) kysytään käyttäjänimi  ja salasana

ohjelman  alussa,  koska  molemmissa  autentikoinneissa  periaatteessa  kyse  on  samasta

asiasta. Seuraavissa kappaleissa kerrotaan (Java Authentication and Authorization Ser­

vice) JAAS­pohjaisen autentikoinnin keskeisistä asioista, joita ovat:

­ Kirjautumisen kontekstin säilyttävän LoginContext –objektin luominen.

­ Takaisinkutsujen  käsittelijät  (callback  handlers),  jotka  esittävät  kirjautumis­

pyynnön käyttäjälle.

­ Kirjautumisen konfiguraatiotiedosto (login configuration file) asettaa luokan, jo­

ta käytetään autentikointimodulina. Näin konfiguraatiota voidaan muuttaa ilman

lähdekoodin muuttamista.

5.2.1 LoginContext –objektin luonti

Kirjautumisen  kontekstin  omaava  objekti  tarvitsee parametreikseen  konfiguraation  ni­

men  ja  takaisinkutsun käsittelijän. Konfiguraation nimi on  määritelty konfiguraatiotie­

dostossa. Objektin luonti noudattaa kieliopillisesti seuraavaa kaava:

import javax.security.auth.login.*;

. . .

LoginContext lc =

    new LoginContext(<config file entry name>,

<CallbackHandler to be used for user interaction>);

Pankkijärjestelmän Test­luokassa se on toteutettu seuraavasti:

import javax.security.auth.login.*;

Page 49: ASPEKTISUUNTAUTUNUT€OHJELMOINTI€€JA … · Luvussa€1€esitellään€aspektisuuntautuneen€ohjelmointitavan€historiaa€ja€käsitteistöä. Luvussa€2€esitellään€AspectJkieli,€joka€toteuttaa€aspektisuuntautuneen€ohjelmoinnin

49

. . .

LoginContext lc =

new LoginContext("Sample",

  new TextCallbackHandler());

lc.login();

5.2.2 Takaisinkutsun käsittelijä

Takaisinkutsun käsittelijä tarjoaa mekanismin autentikointitietojen saamiseksi käyttäjäl­

tä. Se kysyy käyttäjältä nimen ja salasanan joko näytöllä keskusteluikkunassa tai ohjel­

mallisesti.  Käyttäjä  voi  olla  ihminen  tai  toinen  järjestelmän    osa.  Esimerkiksi Text­

CallbackHandler­luokka,  joka  sisältyy  Sunin  JRE 1.4  –pakkaukseen,  toimittaa  au­

tentikointi­informaation kutsuvalle järjestelmälle.

5.2.3 Kirjautumisen konfiguraatiotiedosto

Kirjautumisen konfiguraatiotiedosto asettaa luokan, jota käytetään autentikointi­ modu­

lina.  Kirjautumisen  konfiguraatiotiedoston  rakenne  ja  sisältö  kieliopillisesti  kuvattuna

on seuraavanlainen:

<name used by application to refer to this entry> {

   <LoginModule> <flag> <LoginModule options>;

   <optional additional LoginModules, flags and options>;};

Pankkijärjestelmän esimerkin sample_jaas.config –tiedosto assosioi  tämän konfi­

guraation sample­pakkauksen SampleLoginModule.java – luokkaan. Optiolla de­

bug=true saa tulostettua viestejä käyttäjälle kirjautumisen onnistuttua.

Pankkijärjestelmän sample_jaas.config ­konfiguraatiotiedosto:

Page 50: ASPEKTISUUNTAUTUNUT€OHJELMOINTI€€JA … · Luvussa€1€esitellään€aspektisuuntautuneen€ohjelmointitavan€historiaa€ja€käsitteistöä. Luvussa€2€esitellään€AspectJkieli,€joka€toteuttaa€aspektisuuntautuneen€ohjelmoinnin

50

Sample {

 sample.module.SampleLoginModule required debug=true;

};

SampleLoginModule.java    kysyy  käyttäjä  tunnuksen,  joka  on  "testUser"  ja

salasanan "testPassword", jotka annettuaan käyttäjä saa ilmoituksen  kirjautumisen

onnistumisesta.

Pankkijärjestelmän  autentikointia  ja  kirjautumisen  konfiguraatiota  varten samp­

le_jaas.config –tiedosto  sijoitetaan  johonkin  luokkapolussa olevaan  hakemistoon,

kuten myös tutoriaalin sample ­niminen hakemisto, jonka module­alihakemisto sisäl­

tää SampleLoginModule.java –tiedoston.

Tämän  raportin  pankkijärjestelmä  esimerkissä  käytetään  JAAS­tutorialin  tiedostoja.

Tutoriaali  löytyy Sun­yhtiön verkkosivulta [Sun05]. Tämän autentikointiesimerkin läh­

dekoodi on raportin liitteessä 6.

5.3 Autentikointi AspectJ­ratkaisuna

AspectJ­ratkaisuna  autentikointi  voidaan  toteuttaa  uudelleenkäytettävällä  abstraktilla

perusaspektilla,  jota  voi  käyttää  erilaisten  järjestelmän  autentikointiin.  Perusaspektissa

määritellään  ilmentymämuuttujaan autentikoitu  subjekti  kirjautumisvaiheessa.  Autenti­

koitu subjekti saa arvokseen LoginContext­olion.

Perusaspektille kirjoitetaan aliaspekti,  joka  laajentaa  sen  järjestelmäkohtaiseksi.  Alias­

pektiin  määritellään pointcut­lohko,  jossa  siepataan  autentikointia  tarvitsevat  järjestel­

män operaatiot.

Pankkijärjestelmän  autentikoinnin  mahdollistavat AbstractAuthAspect  ­aspekti

ja konkreettinen BankingAuthAspect­ aliaspekti. Näiden lähdekoodi on liitteessä 7.

Page 51: ASPEKTISUUNTAUTUNUT€OHJELMOINTI€€JA … · Luvussa€1€esitellään€aspektisuuntautuneen€ohjelmointitavan€historiaa€ja€käsitteistöä. Luvussa€2€esitellään€AspectJkieli,€joka€toteuttaa€aspektisuuntautuneen€ohjelmoinnin

51

AbstractAuthAspect­aspektissa  määritellään  ilmentymämuuttujaan  autentikoitu

subjekti kirjautumiskontekstin yhteydessä:

LoginContext lc =

    new LoginContext("Sample",

            new TextCallbackHandler());

    lc.login();

    _authenticatedSubject = lc.getSubject();

Kirjautuminen tapahtuu kerran ja on voimassa koko prosessin ajan kaikille operaatioille.

Autentikoitu subjekti –muuttuja voidaan siirtää myös käyttäväksi muualla, esimerkiksi

servletin  istunto­objektiin.  Järjestelmästä  uloskirjautuessa  subjekti­muuttujan  arvoksi

pitää asettaa null.

AbstractAuthAspect­aspektissa  esitellään  abstrakti authOperation()  –

poincut, joka määritellään aliaspektissa sieppaamaan autentikointia tarvitsevat operaati­

ot.  Perusaspektin before  ­advice  varmistaa,  että  järjestelmä  suorittaa  autentikoinnin

kerran ohjelman ajon aikana.  Jos _authenticatedSubject arvo on null, auten­

tikointi suoritetaan,  jos arvo on not null, autentikointia ei  suoriteta. Näin  järjestel­

mässä toteutuu just­in­time autentikointi, eli se suoritetaan vain silloin, kun jotain järjes­

telmän palvelua tarvitaan, eikä siihen ole vielä kirjauduttu.

Konkreettisessa aliaspektissa määritellään pointcut­lohko, jossa siepataan autentikointia

tarvitsevat  järjestelmän  operaatiot. BankingAuthAspect­aspektin execution  –

advice  voidaan  määritellä  sieppaamaan  myös  ohjelman  käynnistävän main()  –

metodin, jolloin käyttäjätunnukset kysytään ensimmäiseksi.

Page 52: ASPEKTISUUNTAUTUNUT€OHJELMOINTI€€JA … · Luvussa€1€esitellään€aspektisuuntautuneen€ohjelmointitavan€historiaa€ja€käsitteistöä. Luvussa€2€esitellään€AspectJkieli,€joka€toteuttaa€aspektisuuntautuneen€ohjelmoinnin

52

5.4 Auktorisointi

Auktorisointiprosesi päättelee onko käyttäjällä oikeudet käyttää hänen  haluamiaan  jär­

jestelmän toimintoja. Auktorisoinnin esiehtona on että käyttäjä on autentikoitu.

5.4.1 JAAS­pohjainen auktorisointi luokkatoteutuksena

JAAS­pohjaisessa  auktorisoinnissa  järjestelmä  saa  autentikoinnin  alijärjestelmältä  tar­

kistetun käyttäjän subjektin. Tämä Subject –luokan ilmentymä kapseloi käyttäjän tie­

toja kuten tunnisteen ja valtuudet. Kaikkien auktorisointia tarvitsevien operaatioiden on

tarkistettava subjektin valtuudet.

Jokainen  auktorisoinnin  tarkistamista  tarvitseva  metodi  on  kapseloitava action  ­

objektiin,  joka  toteuttaa PrivilegedAction  tai PrivilegedExceptionAc­

tion ­rajapinnan. Näillä molemmilla on ainoastaan run() –metodi, joka suorittaa ha­

lutun operaation. Rajapintojen  ainoa ero on poikkeuksen käsittely, PrivilegedAc­

tion ei  sisällä  poikkeusten  julistusta  (declaration)  lainkaan,  mutta Privilege­

dExceptionAction voi heittää Exception­tyyppisen poikkeuksen.

Action –objekti suoritetaan autentikoidun subjektin puolesta käyttämällä Subject –

luokan  staattista doAsPrivileged(Subject,  PrivilegedAction,  Ac­

cessControlAccess)  ­metodia.  Sen  keskimmäinen  toimintoparametri  voi  olla

myös PrivilegedExceptionAction,  jolloin run()­metodin heittämä tarkistet­

tu poikkeus kääritään ennen sen heittämistä.

Auktorisoitua  toimintoa  tarvitsevien  metodien on  tarkistettava subjektin  valtuudet kut­

sumalla AccessController.checkPermission()  –metodia  ja  välitettävä

permission­objekti,  joka sisältää vaaditun valtuuden. Jos käyttäjällä ei ole valtuuk­

sia, metodi heittää tarkastamattoman AccessControlException­poikkeuksen.

Auktorisoitavalle  järjestelmälle  on  määriteltävä käyttöoikeustiedosto  (policy  file),  joka

asettaa  eri  subjekteille  valtuudet  tiettyihin  operaatioihin. AccessControl­

Page 53: ASPEKTISUUNTAUTUNUT€OHJELMOINTI€€JA … · Luvussa€1€esitellään€aspektisuuntautuneen€ohjelmointitavan€historiaa€ja€käsitteistöä. Luvussa€2€esitellään€AspectJkieli,€joka€toteuttaa€aspektisuuntautuneen€ohjelmoinnin

53

ler.checkPermission() –metodi käyttää tätä tiedostoa ja sallii operaatioiden käy­

tön vain mikäli subjektilla niihin valtuudet.

Edellä esitellylle pankkijärjestelmälle on auktorisoinnin toteuttamiseksi kirjoitettu Ban­

kingPermission  –luokka,  jonka  konstruktorin String  name  –muuttuja  välittää

käyttäjän valtuudet. Muuttujan avulla  luetaan käyttöoikeustiedostosta käyttäjän valtuu­

det. Toisen konstruktorin action­parametria käytetään  instantioimaan valtuutuskohde

käyttöoikeustiedostosta. BankingPermission –luokan lähdekoodi on liitteessä 8.

Liitteessä 8 on myös esimerkki pankkijärjestelmän käyttöoikeudet määrittelevä secu­

rity.policy  ­tiedosto,  jossa  määritellään testUser  ­käyttäjälle  oikeudet  käyttää

kaikkia tilinkäyttöön liittyviä operaatioita.

5.4.2 JAAS­pohjainen auktorisointi AspectJ­toteutuksena

JAAS­pohjainen  auktorisointi  toteutetaan  reitittämällä  auktorisoidut  kutsut  sellaisen

luokan  välityksellä  joka  implementoi  joko PrivilegedExceptionAction­  tai

PrivilegedAction­poikkeuksen,  riippuen  siitä  heittääkö  operaatio  tarkistetun

poikkeuksen.  Worker­objektin  luonti  ­suunnittelumalli  nopeuttaa  tämän  toteuttamista,

koska voidaan  kirjoittaa  aspekti,  joka  suorittaa operaatiot  worker­objektin  välityksellä

Subject.doAsPrivileged() –metodin kautta.

Auktorisointi voidaan modularisoida yhteen aspektiin kirjoittamalla uudelleen käytettä­

vä abstrakti aspekti, joka lisää auktorisoinnin järjestelmään. Tälle perusaspektille kirjoi­

tetaan  järjestelmäkohtainen konkreettinen aliaspekti. Näin saadaan  järjestelmä auktori­

soitua  vähäisellä  koodimäärällä.  Abstrakti  perusaspekti  toteuttaa  auktorisoinnin ohella

myös autentikoinnin. Esimerkkinä  tällaisesta perusaspektista on AbstractAuthAs­

pect­aspekti, jonka lähdekoodi on liitteessä 8.

AbstractAuthAspect­aspekti  ohjaa  kaikki  auktorisointia  tarvitsevien  operaatioi­

den kutsut PrivilegedExceptionAction­rajapinnan toteuttavan anonyymin luo­

Page 54: ASPEKTISUUNTAUTUNUT€OHJELMOINTI€€JA … · Luvussa€1€esitellään€aspektisuuntautuneen€ohjelmointitavan€historiaa€ja€käsitteistöä. Luvussa€2€esitellään€AspectJkieli,€joka€toteuttaa€aspektisuuntautuneen€ohjelmoinnin

54

kan  kautta.  Lisäämällä proceed()­metodi  worker­objektin  suorittavaan run()­

metodiin, kääritään operaation argumentit, joten ne voivat olla mitä tahansa tyyppiltään

ja  lukumäärältään.

AbstractAuthAspect  –aspektissa  esitellään  abstrakti  pointcut authOpera­

tions(), konkreettisessa aliaspektissa  tämä pointcut määrittelee auktorisointia tarvit­

sevat    operaatiot.  Nämä  operaatiot  ovat  samoja,  jotka  tarvitsevat  autentikointia.  Kun

pelkkä sisäänkirjautuminen ohjelmistoon ei riitä resurssien käytön valtuudeksi, operaa­

tiot voidaan eritellä esimerkiksi seuraavasti:

pointcut authenticatedOperations()

    :primaryAuthenticatedOperations()

     || authorizedOperations();

Abstraktissa perusaspektissa esitellään abstrakti getPermission() –metodi,  joka ha­

kee tarvittavat valtuudet. Myös tämä metodi määritellään konkreettisessa aliaspektissa.

Metodi välittää valtuudet operaatioiden suorittamiseen.

Abstraktin  perusaspektin around ­advice  suorittaa  siepatut  operaatiot  autentikoidun

subjektin  puolesta.  Se  luo  auktorisointia  tarvitseville  operaatioille  worker­objektin  ja

suorittaa  ne run()­metodissaan.  Perusaspektin RuntimeException  –poikkeukset

kääritään  joko AuthorizationException­ tai AuthenticationException­

tyyppisiksi poikkeuksiksi.

Konkreettisessa aliaspektissa määritellään järjestelmäkohtainen auktorisointi. Aliaspek­

tiin määritellään vain edellä kerrotulla tavalla authOperations()­pointcut ja get­

Permission()  –metodi.  Metodi  välittää  valtuudet  operaatioon  joinpoint­kohdan

sieppaaman  operaation  nimen  perusteella.  Pankkijärjestelmän  esimerkin  konkreettin

BankingAuthAspect –aliaspektin lähdekoodi on liitteessä 8.

Page 55: ASPEKTISUUNTAUTUNUT€OHJELMOINTI€€JA … · Luvussa€1€esitellään€aspektisuuntautuneen€ohjelmointitavan€historiaa€ja€käsitteistöä. Luvussa€2€esitellään€AspectJkieli,€joka€toteuttaa€aspektisuuntautuneen€ohjelmoinnin

55

6 TRANSAKTIO

Tässä  luvussa  havainnollistetaan  transaktion  hallinnan  ongelmia.  Transaktio  koostuu

atomisista toimenpiteistä, jotka takaavat että järjestelmä säilyttää ristiriidattoman tilansa

ennen toimenpidettä ja sen jälkeen. Atomisuus, eheys, erillisyys ja kestävyys ovat trans­

aktiolta vaadittuja ominaisuuksia.

Esimerkkinä toteutetaan edellä kerrotun osittaisen pankkijärjestelmän transaktion hallin­

ta.  Ensin  kerrotaan  peruslähtökohdat  ja  esitellään  perinteinen  ratkaisu  sekä  AspectJ­

ratkaisu.  Transaktion  hallinta  on  toteutukseltaan  järjestelmän  poikkileikkaava  tehtävä,

joten ratkaisun modularisointi selkeyttää sen toteutusta ja ylläpitoa.

6.1 Ydin tehtävien toteutus

Pankkijärjestelmän  vaatimuksena  on  pysyvyys  ja  tietokannan  eheys.  Yhteys  tietokan­

taan pitää olla taloudellinen. Käyttäjän pitää pystyä suorittamaan haluamansa operaatio

loppuun. Mikäli se ei onnistu, jo tehdyt toimenpiteet perutaan.

Tässä esimerkissä käytetään JDBC­  yhteyttä MySQL­tietokantaan. Tietokannan  taulu­

jen luominen ja konfigurointi on esitetty liitteessä 1.

Kuva 7 esittää UML­notaatiolla  järjestelmän peruslähtökohdat. Kappaleessa 6.2 kerro­

taan transaktion perinteisestä ratkaisusta ja kappaleessa 6.3 AspectJ­ratkaisusta.

Page 56: ASPEKTISUUNTAUTUNUT€OHJELMOINTI€€JA … · Luvussa€1€esitellään€aspektisuuntautuneen€ohjelmointitavan€historiaa€ja€käsitteistöä. Luvussa€2€esitellään€AspectJkieli,€joka€toteuttaa€aspektisuuntautuneen€ohjelmoinnin

56

Kuva 7. Pankkijärjestelmän perusluokat

6.2 Transaktion perinteinen ratkaisu

Tämän  pankkijärjestelmän  toiminnallinen  ydin  on  toteutettu  perinteisillä  java­luokilla.

Järjestelmässä on tilin ja tilinsiirron toteuttavat luokat, sekä tietokantayhteyden ja trans­

aktion päivityksen hyväksyvä luokka. Esimerkin lähdekoodi on liitteessä 9.

AccountJDBCImpl­luokka on Account­rajapinnan konkreettinen toteutus. Luokka

sisältää  rajapinnan  metodien  toteutuksen  lisäksi private­määreisen  metodin,  joka

asettaa tilin saldon. Luokan metodit sisältävät transaktioita. Tämän luokan sisällä meto­

dien suorituksessa ei tarvitse huomioida muiden metodien tekemiä päivityksiä tietokan­

taan.

InterAccountTransferSystem­luokan  ainoa  metodi  siirtää  rahamäärän  tililtä

toiselle.  Tällöin  ohjelman  suorituksessa  tapahtuu sisäkkäisiä  transaktioita  (nested

transactions), mikä vaatii metodien suoritusten koordinointia.

Transaktion  eheyden  vaatimuksen  täyttymiseksi  sekä credit()­  että debit()­

metodien suorituksen täytyy onnistua tai päivitykset tietokantaan pitää perua.

Page 57: ASPEKTISUUNTAUTUNUT€OHJELMOINTI€€JA … · Luvussa€1€esitellään€aspektisuuntautuneen€ohjelmointitavan€historiaa€ja€käsitteistöä. Luvussa€2€esitellään€AspectJkieli,€joka€toteuttaa€aspektisuuntautuneen€ohjelmoinnin

57

DatabaseHelper­luokassa Connection­luokan getConnection()  –metodi

palauttaa tietokantayhteyden objektina. Metodissa voidaan määritellä päivitystapa tieto­

kantaan. Jos sen arvoksi on asetettu connection.setAutoCommit(true), tieto­

kannan  päivityksiä  ei  tarvitse  hyväksyä  ohjelmallisesti,  vaan  se  tapahtuu  välittömästi

ohjelman  suorituksessa. DatabaseHelper.getConnection()­metodi  luo  aina

uuden yhteyden jokaiselle tietokantaoperaatiolle. Siksi ei voida tehdä useita päivityksiä

yhden transaktion sisällä, koska jo tapahtuneita päivytyksiä ei peruta vaikka operaatios­

sa  yksi päivitys  epäonnistuu. Näin ollen  järjestelmä  voi  jäädä  virheelliseen  tilaan ope­

raation  epäonnistuessa.  Tämän  estämiseksi pitää  auto­commit  arvoksi  asettaa false.

Lisäksi samaa yhteysobjektia pitää käyttää kaikille saman operaation tietokannan päivi­

tyksille ja hyväksyä ne kerralla, jos kaikki ovat onnistuneet tai perua, jos jokin päivitys

epäonnisui.

Jos samaa DatabaseHelper­luokan luomaa yhteysobjektia käytetään koko operaati­

on ajan. Tämän toteuttamiseksi on kaksi yleistä tapaa; välitetään yhteysobjekti operaati­

oon osallistuville metodeille argumenttina tai säiekohtaisen varaston käyttäminen.

Yhteysobjektin  välittäminen  metodeille  vaatii  melkoisia  muutoksia  luokkien  toteutuk­

seen.  Tässä  esimerkissä  yhteys  voidaan  luoda InterAccountTransferSystem­

luokan transfer()  –metodissa,  joka  kutsuu debit()­  ja credit()­metodia,  ja

antaa niille   lisäargumentiksi yhteysobjekti. Metodien suoritusta ei hyväksytä erikseen,

vasta kun molemmat metodit on suoritettu onnistuneesti, yhteysobjekti kuitataan Con­

nection –luokan commit()­metodilla ja yhteys suljetaan. Seuraavassa nämä meto­

din koodiin tehdyt muutokset:

public static void transfer(Account from, Account to,

float amount)

throws InsufficientBalanceException {

Connection conn = DatabaseHelper.getConnection();

conn.setAutoCommit(false);

try {

Page 58: ASPEKTISUUNTAUTUNUT€OHJELMOINTI€€JA … · Luvussa€1€esitellään€aspektisuuntautuneen€ohjelmointitavan€historiaa€ja€käsitteistöä. Luvussa€2€esitellään€AspectJkieli,€joka€toteuttaa€aspektisuuntautuneen€ohjelmoinnin

58

to.credit(amount, conn);

from.debit(amount, conn);

conn.commit();

}

catch (Exception ex) {

conn.rollback();

// log exception jne

}

finally {

conn.close();

     }

}

Näistä muutoksista aiheutuu edelleen muutoksia credit() ja debit()­metodeihin.

Laajemmassa järjestelmässä tällaisten muutosten tekeminen voi olla hyvin työläs.

Toinen  ­  edellistä  modularisoidumpi  ­  tapa  välittää  yhteysobjekti  lisäargumenttina  on

käyttää ThreadLocal­luokan  tarjoamaa  säikeiden  varastointia.  Tällöin  on Data­

baseHelper­luokaan  lisättävä  yhteysobjektin  käärivä static final Thread­

Local  ­jäsen,  jolta DatabaseHelper.getConnection()­metodi  määritellään

pyytämään yhteys. Metodi palauttaa varastosta säiekohtaisen yhteyden, jos sellainen on

saatavilla.  Jos  ei  ole,  metodi  luo  uuden  yhteyden  ja  asettaa  sen  varastoon.  Tämä  tapa

modularisoi yhteyden käyttämisen, mutta ei transaktiota tehtäväkokonaisuutena.

Jos vaaditaan, että sisäkkäisessä transaktiossa vain ylätason operaatio voi suorittaa kuit­

tauksen, on tarpeen määritellä ohjelmallisesti kuittauksen suorittaja. Yksittäistä metodia

ei  voi  määritellä  ylätason  operaatioksi,  koska  jokaiseen  transaktioon  pitäisi  määritellä

metodien  taso  erikseen.  Eräs  ratkaisu  on  käyttää  säikohtaista  muuttujaa  tai  lisäargu­

menttia,  joka  ilmaisee  kutsun  tason  tai  syvyyden.  Kutsun  tason  mittaria  kasvatetaan

Page 59: ASPEKTISUUNTAUTUNUT€OHJELMOINTI€€JA … · Luvussa€1€esitellään€aspektisuuntautuneen€ohjelmointitavan€historiaa€ja€käsitteistöä. Luvussa€2€esitellään€AspectJkieli,€joka€toteuttaa€aspektisuuntautuneen€ohjelmoinnin

59

metodin suoritukseen mentäessä ja vähennetään suorituksen päättyessä,  jolloin nollata­

solle palattaessa voidaan suorittaa kuittaus.

Yhteenvetona  tästä pankkijärjestelmän osan perinteisestä  ratkaisusta voidaan huomata,

että sen transaktion hallinnan koodi on hajanaisesti useissa metodeissa ja moduleissa, ja

sen muunneltavuus on sidottu liiketoimintalogiikkaan.

6.3 AspectJ­kielinen transaktion ratkaisu

Tässä  luvussa  muodostetaan  edellä  esitetystä  pankkijärjestelmän  osasta  AspectJ­

kielinen ratkaisu. Järjestelmän perusluokat ovat samat kuin perinteisen järjestelmän rat­

kaisua esittävässä kuvassa 7, joka esitettiin luvussa 6.1.

Järjestelmän korkean tason vaatimuksena on:

­ Ratkaisun  on  oltava  uudelleen  käytettävä.  Tätä  ratkaisua  käytetään  muissakin

JDBC­pohjaisten järjestelmien kehitysprojekteissa.

­ Transaktion päivitysoperaatioiden on käytettävä yhtä yhteysobjektia,  joka sisäl­

tää transaktion tilan. Kun metodin kontrollivirrassa  tarvitaan transaktion hallin­

taa, yhteyden luonnin jälkeen kaikki tämän kontrollivirran päivitykset käyttävät

samaa  yhteysobjektia.  Näin  tämä  yhteysobjekti  muodostaa  operaatioiden  kon­

tekstin.

­ Kaikki  transaktion päivitykset  hyväksytään, kun ylätason operaatio päättyy on­

nistuneesti.  Jos  jokin  päivitys  epäonnistuu  tai  jokin  liiketoimintametodi  heittää

poikkeuksen, yhteysobjektin kaikki päivitykset on peruttava (roll back).

Ratkaisun on uudelleen käytettävyys toteutuu luomalla abstrakti aspekti,  joka toteuttaa

pääpiirteet transaktion logiikasta. Logiikan lisäksi tämä aspekti sisältää abstraktit point­

cut –esittelyt transaktion operaatioille ja yhteyden saamiseksi.

Ylätason operaatioiden sieppaamiseksi määritellään pointcut, joka sieppaa ne ajon ope­

raatiot jotka eivät jo ole toisen transaktion operaation kontrollivirrassa. Ylätason operaa­

Page 60: ASPEKTISUUNTAUTUNUT€OHJELMOINTI€€JA … · Luvussa€1€esitellään€aspektisuuntautuneen€ohjelmointitavan€historiaa€ja€käsitteistöä. Luvussa€2€esitellään€AspectJkieli,€joka€toteuttaa€aspektisuuntautuneen€ohjelmoinnin

60

tioiden onnistumista valvotaan poikkeuksien hallinnalla. Transaktion operaatioiden suo­

ritus  etenee  around  advice  –määrittelyn  try/catch  –lohkossa.  Operaatio  on  onnistunut

mikäli se ei heitä yhtään poikkeusta.

Yhden  yhteysobjektin  käytön  varmistamiseksi  transaktion  sisällä  määritellään  advice­

ohje transaktion kontrollivirrassa yhteyden luovalle joint point –kohdalle. Kun yhteyttä

tarvitaan ensimmäisen kerran  siepatussa  operaatiossa,  yhteys  hankitaan  ja  se  varastoi­

daan aspektin  sisällä  ilmentymä muuttujaan (instance variable). Kun yhteyttä tarvitaan

seuraavan kerran, advice palauttaa varastoidun yhteyden ja välittää siepatun operaation.

Aspekti assosioidaan myös ylätason operaatioiden kontrollivirtaan. Koska aspekti varas­

toi  yhteysobjektin  jota  käytetään  kaikkiin  päivityksiin,  aspektin  ilmentymä  sisältää

transaktion kontekstin niin kauan kuin transaktio kestää.

Transktiota  tarvitsevan  järjestelmän osan    toteutukseen määritellään konkreettinen ali­

aspekti. Aliaspektissa  määritellään konkreettinen  pointcut,  joka sieppaa perustoteutuk­

sesta    transaktion  join  point  –kohdat  ja  konkreettinen  pointcut,  joka  sieppaa  yhteyden

muodostamisen join point –kohdat.

Yhteyden  luomiseen  voidaan  käyttää  erilaisia  tapoja,  kuten  apuluokkia  tai  resurssien

säiliöitä  (resource  pooling).  Tämän  vuoksi  perusaspektissa  esitellään  yhteyksiä  varten

abstrakti pointcut, joka määritellään konkreettisessa aliaspektissa. Kuva 8 esittää UML­

notaationa pankkijärjestelmän transaktion hallinnan aspekteja.

Page 61: ASPEKTISUUNTAUTUNUT€OHJELMOINTI€€JA … · Luvussa€1€esitellään€aspektisuuntautuneen€ohjelmointitavan€historiaa€ja€käsitteistöä. Luvussa€2€esitellään€AspectJkieli,€joka€toteuttaa€aspektisuuntautuneen€ohjelmoinnin

61

Kuva 8.  Pankkijärjestelmän transaktion hallinnan aspektit.

6.3.1 JDBCTransactionAspect­aspektin koodin selitys

Tämän  AspectJ­kielisen  ratkaisun  lähdekoodi  on  liitteessä  10. JDBCTransac­

tionAspect –aspektin selitys kohdittain:

percflow(topLevelTransactedOperation()) assosioi  aspektin  ilmenty­

män  transaktion  ylätason  operaation  kontrollivirtaan.  Aliaspektin transactedOpe­

ration()–pointcut  määrittelee  transaktion  operaatiot,  joita  kutsuttaessa  ilmentymä

luodaan jos se ei kuulu jo meneillään olevaan transaktioon. Ilmentymä säilyttää transak­

tion tilan. Tätä ratkaisua voidaan käyttää, jos transaktioon osallistuu vain yksi järjestel­

mä.

Abstraktit obtainConnection­pointcut  ja transactedOperation()–pointcut

määritellään konkreettisessa aliaspektissa. Nämä käsittelevät yhteyden luomisen ja ope­

raatioiden suorituksen.

topLevelTransactedOperation()­pointcut määritellään ylätason operaatioksi.

Transaktion  hallinnan  suorittamiseksi  sen  tukena  on  abstrakti transactedOpera­

tion()­pointcut,  sekä Object around  ­advice.  Aspektin  uusi  instanssi  assosioi­

Page 62: ASPEKTISUUNTAUTUNUT€OHJELMOINTI€€JA … · Luvussa€1€esitellään€aspektisuuntautuneen€ohjelmointitavan€historiaa€ja€käsitteistöä. Luvussa€2€esitellään€AspectJkieli,€joka€toteuttaa€aspektisuuntautuneen€ohjelmoinnin

62

daan  ylätason  operaatioon.  Kun  sellaisen  join  point  –kohdan  suoritus  alkaa,  luodaan

konkreettisen aliaspektin uusi instanssi.

Object around –advice,  joka ohjeistaa topLevelTransactedOperation(),

vie  siepatun  operation  try/catch  ­lohkoon. Try­lohkossa  kutsutaan proceed()  –

metodia  operaation  suorituksen  jatkamiseksi.  Jos  operaatio  heittää  suorituksen  aikana

poikkeuksen,  suoritus  siirtyy catch­lohkoon  joka  kutsuu  yhteysobjektin roll­

back()­metodia, jolloin päivitykset perutaan. Finally­lohko sulkee yhteyden.

if(_connection != null)  käsittelee  tapaukset  joissa  yhteyttä  tietokantaan  ei

luotu,  koska  liiketoimintalogiikka  ei  tarvinnut  päivityksiä  tai  kyselyjä  tietokannasta.

(Ylätason operaatio voi sisältää tällaisia alioperaatioita suorituksensa loppuvaiheessa.)

Tässä  transaktion  hallinnan ratkaisussa    samaa yhteyttä   käytetään operaation kaikkiin

päivityksiin,  jolloin  ne  voidaan  hyväksyä  kerralla  kutsumalla  yhteysobjektin com­

mit()­metodia. Connection around() –advice tarkistaa, onko connection –

instanssin arvo null. Mikäli  se on null, ylätason operaation suoritus  tarvitsee en­

simmäisen  kerran  yhteyttä.  Seuraavaksi  advice­lohko  hankkii  yhteyden  ja  kytkee  sen

automaattisen  hyväksynnän  pois  päältä  metodissa setAutoCommit(false).  Jos

operaatio  on  onnistunut  yhteysobjekti  kuitataan commit()­metodilla.  Perättäisille

yhteysobjektin  kutsuille  advice­lohko  palauttaa  varastoidun  yhteysobjektin  sen  sijaan,

että loisi uuden.

TransactionException määritellään ajonaikaisena poikkeuksena. Tämän poikke­

uksen heittäminen ilmaisee kutsujalle, että transaktio on epäonnistunut ja kääritty poik­

keus ilmaisee epäonnistumisen syyn.

Poikkeusten pehmentämisellä vältytään try/catch­lohkojen määrittelyltä rollback()­

ja close()­metodien kutsuissa.

Koska  tässä  ratkaisussa  vain JDBCTransactionAspect  ­aspekti  suorittaa  kutsut

yhteysobjekteille,  määritellään koodausta ohjaava illegalConnectionManage­

ment()­poincut  ja around() advice­lohko, jotka käsittelevät aspektin ulkopuolelta

Page 63: ASPEKTISUUNTAUTUNUT€OHJELMOINTI€€JA … · Luvussa€1€esitellään€aspektisuuntautuneen€ohjelmointitavan€historiaa€ja€käsitteistöä. Luvussa€2€esitellään€AspectJkieli,€joka€toteuttaa€aspektisuuntautuneen€ohjelmoinnin

63

määritellyt virheelliset kutsut. Tällaisia kutsuja voisi  tehdä esimerkiksi pankkijärjestel­

män määrittelyssä kirjoittamalla uusia transaktioon liittyviä hyväksymiskäytäntöjä  kut­

suen Connection.setAutoCommit()­metodia.

illegalConnectionManagement()­poincut sieppaa kaikki yhteyden  hallinnan

join point –kohdat ja around() advice­lohko estää ohjelmoijaa käyttämästä niitä. Ad­

vice­lohkon sijaan tai sen ohella voidaan määritellä myös käännöksen aikaisen virheen

tulostus declare error –lauseella seuraavasti:

declare error : illegalConnectionManagement()

:  “Do not call close(), commit(), rollback(),or   setAutoCommit() on Connectin objects fromhere”;

6.3.2 BankingTransactionAspect­aspektin koodin selitys

Suurin  osa  transaktion  toiminnallisuudesta  on  määritelty  abstraktissa JDBCTransac­

tionAspect­aspektissa. Sitä laajentavaan konkreettiseen BankingTransactionAs­

pect­aspektiin tarvitaan vain kaksi pointcut­määrittelyä pankkijärjestelmän transaktion

hallinnan toteuttamiseksi.

transactedOperation()­pointcut  sieppaa  transaktion  tukea  tarvitsevien  metodien

suorituksen  ja optainConnection()­pointcut  määrittelee  kaikki  metodien  kutsut

joita käytetään tietokanta yhteyksien saamiseksi.

6.4 Yksi transaktio – useita alijärjestelmiä

Yhdessä transaktiossa joudutaan usein suorittamaan operaatioita, joihin osallistuu useita

alijärjestelmiä.  Lisäksi  voi  olla  vaatimuksena  että  jokaisella  alijärjestelmällä  on  oma

aliaspekti,  jonka  poincut­lohkot  määrittelevät  transaktion  tukea  tarvitsevat  operaatiot.

Page 64: ASPEKTISUUNTAUTUNUT€OHJELMOINTI€€JA … · Luvussa€1€esitellään€aspektisuuntautuneen€ohjelmointitavan€historiaa€ja€käsitteistöä. Luvussa€2€esitellään€AspectJkieli,€joka€toteuttaa€aspektisuuntautuneen€ohjelmoinnin

64

Näin  alijärjestelmiin  tehtävät  muutokset  aiheuttavat  transaktion  osalta  muutoksia  vain

aliaspektissa. Tällöin on varmistettava etteivät muutokset aiheuta ristiriitoja transaktion

hallinnassa.

Näiden vaatimusten ratkaisemiseksi voidaan käyttää Osallistuja­suunnittelumallia,  jon­

ka mukaisesti tehdään jokaiselle transaktion osapuolena olevalle alijärjestelmälle trans­

aktiota  tukeva  aliaspekti.  Nämä  sisäaspektit  laajentavat  abstraktin JDBCTransac­

tionAspect ­perusaspektin. Ne voidaan toteuttaa itsenäisinä aliaspekteina, tai  luokki­

en sisäaspekteina.

Pankkijärjestelmä esimerkkissä AccountJDBCImpl­ ja InterAccountTransfer­

System­ luokat ovat toiminnallisesti erillisiä alijärjestelmiä, joten niihin voidaan sovel­

taa edellä kerrottua Osallistuja­suunnittelumallia. Tässä esimerkissä aliaspektit  lisätään

alijärjestelmien  luokkiin  sisäaspekteina.    Järjestelmän  rakennetta   havainnollistaa kuva

9.

6.4.1 TransactionParticipantAspect­aspektin selitys

Liitteessä  11    on AccountJDBCImpl­  ja InterAccountTransferSystem­

luokkien tämän ratkaisutavan lähdekoodi.

 Näiden  luokkien TransactionParticipantAspect­sisäaspektit  laajentavat

JDBCTransactionAspect­aspektin.  Tämän  laajennusominaisuuden  vuoksi In­

terAccountTransferSystem­luokan  sisäaspektissa  joudutaan  määrittelemään

yhteyden  hakeva obtainConnection()­pointcut,  joka  ei  sisällä  yhtään  join point­

kohtaa,  koska  tämä  luokka  ei  saa  hakea  koskaan  itse  yhteyttä.  Luokan  sisäaspektien

transactedOperation()­poincut  sieppaa  luokansa  transaktiota  tarvitsevien  ope­

raatioiden suoritukset.

Vaikka tämä ratkaisutapa mahdollistaa transaktion hallinnan kapseloinnin JDBCTran­

sactionAspect ­perusaspektiin, voi syntyä ajonaikaisia ongelmia jos eri osapuolten

aliaspektien instanssit eivät käytä samaa yhteysobjektia. Näin ollen vain osa operaatios­

Page 65: ASPEKTISUUNTAUTUNUT€OHJELMOINTI€€JA … · Luvussa€1€esitellään€aspektisuuntautuneen€ohjelmointitavan€historiaa€ja€käsitteistöä. Luvussa€2€esitellään€AspectJkieli,€joka€toteuttaa€aspektisuuntautuneen€ohjelmoinnin

65

ta saattaa onnistua, esimerkiksi tilinsiirrossa vastaanottajan tilia voidaan hyvittää vaikka

maksavan tilin veloitusoperaatio on epäonnistunut.

 Jotta transaktion  hallinnassa  voidaan käyttää useita alijärjestelmien aspekteja,  on var­

mistuttava  että  transaktion  päivityksiin  käytetään  samaa  yhteysobjektia  silloinkin,  kun

eri aspektit sieppaavat  transaktion aikana erillisiä operaatioita. Päivityksestä ja huoleh­

ditaan transaktion toteuttavassa perusaspektissa,  johon tehtävistä muutoksista kerrotaan

tarkemmin seuraavassa luvussa.

Page 66: ASPEKTISUUNTAUTUNUT€OHJELMOINTI€€JA … · Luvussa€1€esitellään€aspektisuuntautuneen€ohjelmointitavan€historiaa€ja€käsitteistöä. Luvussa€2€esitellään€AspectJkieli,€joka€toteuttaa€aspektisuuntautuneen€ohjelmoinnin

66

Account­luokka

+credit( amount:float)+debit( amount:float)+getAccountNumber()+getBalance()

AccountJDBCImpl­luokka

+credit( amount:float )+debit( amount:float )+getAccountNumber()+getBalance()­setBalance()+<<aspect>>TransactionParticipantAspect( )

DatabaseHelper­luokka

getConnection( )

TransactionParticipantAspect

#<<pointcut>>transactedOperation()#<<pointcut>>optainConnection()

InterAccountTransferSystem­luokka

+transfer( account1:Account, account2:Account : Account, amount:float)+<<aspect>>TransactionParticipantAspect ( )

impelments

sisäaspektisisäaspekti

 JDBCTransactionAspect­_connection : Connection

#<<pointcut>>transactedOperation()#<<pointcut>>obtainConnection()#<<pointcut>>inTransactedOperation(TransactionContext)<<advice>>around():transactedOperation() && !inTransactedOperation(TransactionContext)<<abstract  class>>TransactionContext extends RunnableWithReturn() : Connection

extends

RunnableWithReturn implements Runnable

getReturnValue: Object( )

Kuva 9. Pankkijärjestelmä sisältää kaksi transaktioon osallistuvaa alijärjestel­

mää, joiden transaktion hallintaa tuetaan sisäaspekteilla.

Page 67: ASPEKTISUUNTAUTUNUT€OHJELMOINTI€€JA … · Luvussa€1€esitellään€aspektisuuntautuneen€ohjelmointitavan€historiaa€ja€käsitteistöä. Luvussa€2€esitellään€AspectJkieli,€joka€toteuttaa€aspektisuuntautuneen€ohjelmoinnin

67

6.4.2 Usean alijärjestelmän transaktion toteuttava perusaspekti

Edellä  luvussa  6.3  esitetyssä  versiossa  abstrakti JDBCTransactionAspect  ­

perusaspekti huolehti kahdesta roolista. Se varastoi yhteysobjektin,  johon kaikki  trans­

aktion operaatiot pystyvät viittaamaan sekä huolehti transaktion hyväksymisestä tai pe­

rumisesta. Tässä  luvussa esitellään perusaspekti,  jossa nämä roolit on eroteltu. Aspekti

määritellään  vastuulliseksi  pelkästään  transaktion  hyväksymisestä  ja  perumisesta,  ja

käytetään hyväksi erillistä transaktion kontekstin objektia, joka varastoi yhteyden.

Tämän erillisyyden toteuttamiseksi perusaspektissa käytetään oletusarvoista assosiointia

percflow­assosiaation  sijaan,  sekä  poistetaan _connection  ­muuttuja  aspektista.

Oletusarvoinen  (default)  assosiaatio  johtaa  siihen,  että  jokaisesta  aliaspektista  luodaan

korkeintaan  yksi  instanssi  ohjelman  suorituksen  aikana.  Koska _connection  ­

instanssi    poistetaan  aspektista  se  on  tilaton  aspekti,  eivätkä  aspektin  instanssit  tässä

ratkaisussa  ilmaise  transaktion  kontekstia.  Worker­objektin  luonti  suunnittelumallia

käytetään luomaan automaattisesti Worker­objekti jokaiselle uudelle transaktiolle. Wor­

ker­objektin tehtävänä on varastoida yhteysobjekti, näin Worker­objekti palvelee trans­

aktion kontekstina.

Worker­objekti  luodaan transaktion hallintaa tarvitseville ylätason operaatioille ja siten

käsitellään  tätä  operaatiota  worker­metodina.  Worker­objektin run()­metodi  sisältää

worker­metodin  joka sisältää transaktion hallinnan  logiikan, eli operaation hyväksymi­

sen tai perumisen. Kun suoritetaan ensimmäinen transaktion hallintaa tarvitseva metodi,

luodaan  yhteysobjekti  joka  varastoidaan  Worker­objektiin.  Toteutuksessa  käytetään

context­objektia varmistamaan, ettei  luoda ylimääräistä yhteysobjektia kun Worker­

objektin run()­metodin kontrollivirrassa saadaan käsiteltäväksi  jokin uusi  join point –

kohta.

Aspektiin implementoidaan TransactionContext­luokka, joka laajentaa Runna­

bleWithReturn­luokan.  Jokaisen  konkreettisen  aliluokan  pitää  implementoida

run()­metodi, joka suorittaa worker­metodin ja asettaa _returnValue­jäsenen ope­

raation tulokseen. Uusi context­objekti  luodaan kaikille transaktion aloittaville ope­

Page 68: ASPEKTISUUNTAUTUNUT€OHJELMOINTI€€JA … · Luvussa€1€esitellään€aspektisuuntautuneen€ohjelmointitavan€historiaa€ja€käsitteistöä. Luvussa€2€esitellään€AspectJkieli,€joka€toteuttaa€aspektisuuntautuneen€ohjelmoinnin

68

raatioille elleivät ne jo ole transaktion kontekstin run()­metodin suorituksen kontrolli­

virrassa.  Kukin  transaktioon osallistuva aspekti voi  luoda  transaktion kontekstin,  uutta

kontekstia ei luoda operaatiolle, joka on jo osa transaktion kontekstia. Koska transaktion

hallinta suoritetaan vain context­objektin kautta, uutta kontekstia ei luoda sisäkkäisil­

le operaatioille. Liitteessä 11 on tämän usean alijärjestelmän transaktion esimerkin läh­

dekoodi.

6.4.3 Muutetun JDBCTransactionAspect­aspektin koodin selitys

Aspektin percflow­assosiaatio  on  muutettu  oletusarvoiseksi  assosiaatioksi.  Aspekti

sisältää  abstraktit transactedOperation()­  ja obtainConnection()­

pointcut esittelyt, jotka määritellään konkreettisissa aspekteissa.

inTransacteOperations()­pointcut  sieppaa TransactionContext.run()

­metodin kontrollivirran  ja taltioi metodiin assosioidun objektin,  joka välitetään kutsu­

pinoon. Tämä pointcut tutkii kuuluuko operaatio jo meneillään olevaan transaktioon.

Object around() ­advice määrittelee transactedOperations()ja inTran­

sacteOperations()­pointcut määrittelyjen perusteella ne join point –kohdat, jotka

eivät vielä ole transaktion kontekstin suorituksessa ja luo tarvittaessa uuden transaktion

kontekstin.  Lohkon run()­metodin  määrittely  on  samanlainen  kuin  ensimmäisessä

versiossa. Tässä toteutuu worker­objektin luonti.

Connection around()­advice  ohjeistaa  yhteyden  hankkimista  ja  tarvitsee  suori­

tuksessa  olevan  transaktion  kontekstin  objektia,  jotta  se  voi  käyttää  (access)  sen

_connection­objektia. inTransacteOperations()­pointcut  sieppaa  tämän

kontekstin.  Tässä  on  sovellettu  madonreikä­suunnittelumallia  luomaan  suora  yhteys

transaktion kontekstin objektin run()­metodin ja yhteyttä tarvitsevan metodin välille.

Abstrakti TransactionContext­luokka  laajentaa RunnableWithReturn­

luokan. Luokan _connection ­muuttuja säilyttää transaktion yhteysobjektin.

Page 69: ASPEKTISUUNTAUTUNUT€OHJELMOINTI€€JA … · Luvussa€1€esitellään€aspektisuuntautuneen€ohjelmointitavan€historiaa€ja€käsitteistöä. Luvussa€2€esitellään€AspectJkieli,€joka€toteuttaa€aspektisuuntautuneen€ohjelmoinnin

69

6.5 JTA­pohjainen transaktion hallinta

Tässä  raportissa  edellä  esitellyt  järjestelmät  perustuivat  JDBC­pohjaiseen  transaktion

tukeen.  Nykyaikaisissa  tietojärjestelmissä  vaatmukset  ovat  kuitenkin  laajempia.  Usein

tarvitaan hajautettua transaktion hallintaa ja mukana on useita resursseja sekä tietokan­

toja. Operaatioissa joudutaan päivittämään myös muiden järjestelmänosien tai ERP (En­

terprise  Recourse  Planning)  –järjestelmien  tietokantoja.  Näissä  tapauksissa  transaktio

käsittelee useita yhteysobjekteja.

Transaktio voi ulottua myös  monenlaisiin  resursseihin. Esimerkiksi  samassa  transakti­

ossa voidaan päivittää tietokantaa  ja  lähettää viestejä  jonoon käyttäen JMS (Java Mes­

sage Service) –palvelua. Tällöin  sekä tietokannan päivityksen että viestijonon  lähetyk­

sen pitää onnistua, jotta järjestelmä säilyttää ehyen (consistent) tilansa. Nämä tapaukset

vaativat (Transaction Processing) TP­monitorin käyttöä, jolla koordinoidaan resurssien

transaktion  onnistumista.  Tällöin  resurssien  (kuten  tietokantojen  ja  JMS  viestityksen

väliohjelmistojen)  pitää  pystyä  yhteistyöhön  TP­monitorin  kanssa.  Monitoroinnissa

ohjelmallisten rajapintojen käyttö, kuten JTA (Java Transction API), mahdollistavat TP­

monitorin soveltavan käytön erilaisissa ympäristöissä.

Käytettäessä  puhtaasti  olio­suuntaunutta  ohjelmointitekniikkaa,  JTA  ei  mahdollista

transaktion  tehtävien  eriyttämistä  ydintehtävistä.  Tämä  johtuu  siitä,  että  toteutuksessa

transaktion  luonti, hyväksyminen  ja peruminen  leviävät kaikkiin moduleihin,  joissa on

transaktion hallintaa vaativia operaatioita. JTA tarjoaa läpinäkyvyyttä käytettävään TP­

monitorointiin, mutta vaatii sen API:n kutsumista useista ydinmoduuleista.

AspectJ­kielen käyttö yhdessä JTA:n kanssa mahdollistaa transaktion hallinnan modula­

risoinnin  poikkileikkaukselliseksi  tehtäväksi.  Liitteessä  12  on  abstrakti  aspekti JTA­

TransactionAspect,  joka kapseloi  kaikki  JTA­pohjaiset  transaktiot. Tuekseen  se

tarvitsee yhden tai useampia konkreettisia aliaspekteja,  joissa määritellään transac­

tedOperation()­pointcut sieppaamaan transaktion tukea tarvitsevat operaatiot.

Page 70: ASPEKTISUUNTAUTUNUT€OHJELMOINTI€€JA … · Luvussa€1€esitellään€aspektisuuntautuneen€ohjelmointitavan€historiaa€ja€käsitteistöä. Luvussa€2€esitellään€AspectJkieli,€joka€toteuttaa€aspektisuuntautuneen€ohjelmoinnin

70

Tämä perusaspekti poikkeaa JDBCTransactionAspect­aspektista vain seuraavilta

osin:

JTATransactionAspect­aspektissa käytetään  transaktion  hallintaan UserTran­

saction  –objektia,  joka  tarjoaa  API:n  transaktion  hyväksymiseen  ja  perumiseen.

Transaktio  alussa  kutsutaan UserTransaction.begin(),  hyväksyttäessä User­

Transaction.commit(), ja peruttaessa UserTransaction.rollback().

Tässä aspektissa ei  tarvita pointcut­  ja advice­lohkoa takaamaan saman yhteysobjektin

käyttöä.  JTA:ta  käytettäessä  ei  yksittäiseen  päivitykseen  tarvitse  käyttää  vain  yhtä  re­

surssia, kuten tietokantayhteyttä.

Tätä aspektia käytettäessä on käännösympäristössä hyvä käyttää valvovia menettelyta­

pojen sääntöjä  takaamaan,  ettei aspektia käytetä muille kuin  JTA:han sopiville  resurs­

seille.

Page 71: ASPEKTISUUNTAUTUNUT€OHJELMOINTI€€JA … · Luvussa€1€esitellään€aspektisuuntautuneen€ohjelmointitavan€historiaa€ja€käsitteistöä. Luvussa€2€esitellään€AspectJkieli,€joka€toteuttaa€aspektisuuntautuneen€ohjelmoinnin

71

7 YHTEENVETO

Aspektisuuntautunut  ohjelmointitekniikka  mahdollistaa  ohjelmiston  toiminnallisuuden

modularisoinnin  aspektien  avulla.  Aspekti  laajentaa  oliosuuntautuneen  ohjelmoinnin

luokkien  käyttötapaa  toteutuksessa.  Toteutusta  voidaan  tiivistää  muutamaan  aspektiin

sen  sijaan,  että  koodaus  leviäisi  laajalle  ohjelmiston  rakenteeseen.  Modularisointi  sel­

keyttää  ohjelmiston  rakennetta  ja  parantaa  sen  uudelleen  käytettävyyttä.  Perinteiset

suunnittelumallit ovat silti edelleen käytettävissä.

Tämän  raportin  esimerkeissä  esitetyt  aspektit  ovat  rakenteeltaan  uudelleen käytettäviä

ratkaisuja. Niissä toteutetaan käyttäjän kirjautuminen järjestelmään ja auktorisointi, jos­

sa käyttäjälle annetaan valtuuksia käyttää tiettyjä resursseja ja järjestelmän operaatioita,

joihin tarvitaan transaktion tukea. Esimerkkien ratkaisut täyttävät modulaarisuuden vaa­

timuksen, koska kukin ohjelmiston poikkileikkauksellinen tehtävä tai huolehdittava asia

on toteutettu selkeästi erillisessä ohjelman osassa,  joka koostuu muutamasta aspektista.

Ratkaisut eivät vaadi suuria muutoksia sovellettaessa niitä samankaltaisiin järjestelmiin.

Page 72: ASPEKTISUUNTAUTUNUT€OHJELMOINTI€€JA … · Luvussa€1€esitellään€aspektisuuntautuneen€ohjelmointitavan€historiaa€ja€käsitteistöä. Luvussa€2€esitellään€AspectJkieli,€joka€toteuttaa€aspektisuuntautuneen€ohjelmoinnin

72

LÄHTEET

[ElF01] Elrad  T.,  Filman  r.,  Bader  A., The  Aspect  Oriented  Programming,  Chi­

cago,2001,(ACM 2005)

[HiH04] Hilsdale  E.,  Hugin  J., Advice  Weaving  in  AspectJ,  Lancaster  UK,  2004

(ACM, 13.1.2005)

[Ken99] Kendall E. A., Role model designs and implementations with aspect­

oriented programming,  Denver US, October 1999, ACM 17.1.2005

[LaC03] Lafferty  D.,  Cahill  V., Language­independent  aspect­oriented  program­

ming, Trinity College Dublin, October 2003 (ACM, 13.1.2005)

[Lad03] Laddad  R., AspectJ  in  Action  Practical  Aspect­Oriented  Programming,

Manning Publications Co, USA, 2003.

[Sun05] JAAS Authentication Tutorial, viitattu 12.2.2005 , Saatavilla

http://java.sun.com/j2se/1.4.2/docs/guide/security/jaas/tutorials/GeneralAc

nOnly.html

[Xer03] Xerox Corporation, Palo Alto Research Center, The AspectJ Programming

Guide,  viitattu  20.2.2005,    saatavilla:  http://dev.eclipse.org/viewcvs/  in­

dextech.cgi/~checkout~/aspectj­home/doc/progguide/index.html.

OHJELMISTOT  JA LÄHDEKOODIT:

[ECL05] AspectJ Compiler (aspectj­1.2.1.jar) ­ohjelmisto, viitattu 15.1.2005 saata­

villa: http://eclipse.org/aspectj/,

[ECL05a] Eclipse Platform SDK 3.0.1 ja Eclipse AspectJ Development Tools, viitattu

18.1.2005, saatavilla: http://eclipse.org/downloads/index.php

[MYS05] MySQL  4.1­ohjelma,  viitattu  28.2.2005  Saatavilla:

http://dev.mysql.com/downloads/

Page 73: ASPEKTISUUNTAUTUNUT€OHJELMOINTI€€JA … · Luvussa€1€esitellään€aspektisuuntautuneen€ohjelmointitavan€historiaa€ja€käsitteistöä. Luvussa€2€esitellään€AspectJkieli,€joka€toteuttaa€aspektisuuntautuneen€ohjelmoinnin

73

[Lea05] Lea  Doug, JSR166­luokkakirjasto, viitattu  10.3.2005  saatavilla:

http://gee.cs.oswego.edu/dl/concurrency­interest/index.html.

[Lea05a]  Lea Doug, Concurrent­luokkakirjaston kotisivu, viitattu 10.3.2005, saata­

villa:

http://gee.cs.oswego.edu/dl/classes/EDU/oswego/cs/dl/util/concurrent/  in­

tro.html

[Lea03b]  Lea  Doug, AspectJ  in  Action  ­kirjan  esimerkkien  lähdekoodi,  saatavilla:

http://www.manning.com/catalog/view.php?book=laddad&item=source

[Lea03c]  Lea Doug, JSR 166 –ohjelmisto ja dokumentaatio, viitattu 10.3.2005, saa­

tavilla: http://gee.cs.oswego.edu/dl/concurrency­interest/index.html

[Lea03d]  Lea  Doug, backport­util­concurrent  luokkakirjasto,  viitattu  10.3.2005,

saatavilla: http://www.mathcs.emory.edu/dcl/util/backport­util­concurrent/

Muita resursseja:

Suunnittelumallien toteutuksia:

Implementations of GoF Design Patterns  in Java  and AspectJ, saatavilla:

http://www.cs.ubc.ca/~jan/AODPs/