...
SOA-arkkitehtuurissa
...
palvelut
...
ovat
...
tilattomia
...
ja
...
proseduraalisia,
...
joukko
...
operaatioita
...
ja
...
niihin
...
liittyviä
...
rakenteitä.
...
Lähestymistapa
...
on
...
siten
...
vastakohta
...
Domain
...
driven
...
-tyyppiselle
...
ohjelmoinnille,
...
jossa
...
oliot
...
ovat
...
tilallisia
...
ja
...
huolehtivat
...
itse
...
operaatioista.
...
2.4.1
...
Rajapintoihin
...
liittyvät
...
ongelmat
...
Sisäisten
...
rakenteiden
...
näkyminen
...
rajapinnassa
...
Palvelurajapinnat
...
ovat
...
julkisia
...
ja
...
niihin
...
liittyy
...
useampia
...
käyttöliittymiä
...
tai
...
integraatioita.
...
SOA-arkkitehtuurissa
...
täytyy
...
huolehtia
...
siitä,
...
etteivät
...
tietokantaan
...
tehtävät
...
muutokset
...
heijastu
...
rajapintaan
...
ja
...
riko
...
siihen
...
yhteydessä
...
olevia
...
käyttöliittymiä.
...
Jos
...
esimerkiksi
...
tietojen
...
tallennukseen
...
on
...
käytetty
...
JPA
...
(Hibernate)
...
tekniikkaa,
...
on
...
huolehdittava
...
siitä,
...
ettei
...
tietokantatauluja
...
kuvaavia
...
entity-olioita
...
ole
...
käytetty
...
julkaistussa
...
rajapinnassa
...
parametreinä.
...
Jos
...
näin
...
on
...
tehty,
...
rajapinta
...
ei
...
voi
...
olla
...
muuttumaton
...
(tai
...
ainakin
...
erittäin
...
vaikea
...
pitää
...
sellaisena),
...
eikä
...
ratkaisu
...
tuo
...
oikeastaan
...
mitään
...
lisäarvoa
...
siihen
...
että
...
oltaisiin
...
suoraan
...
yhteydessä
...
tietokantaan
...
JDBC:n
...
avulla.
...
Tämä
...
ongelma
...
korostuu
...
SOA-ratkaisussa,
...
jossa
...
lähtökohtaisesti
...
rajapinnat
...
ovat
...
kenen
...
tahansa
...
muun
...
palvelun
...
käytettävissä
...
(ei
...
välttämättä
...
ole
...
edes
...
saman
...
toimittajan
...
tekemiä).
...
Taaksepäin
...
yhteensopivuus
...
Jossain
...
palvelun
...
kehityskaaren
...
vaiheessa
...
voi
...
tulla
...
tarvetta
...
muuttaa
...
julkaistua
...
rajapintaa.
...
Esimerkiksi
...
halutaan
...
tehdä
...
uusi
...
toiminto,
...
jossa
...
toimintalogiikkaa
...
tulee
...
muuttaa
...
tai
...
jokin
...
tietokantakenttä
...
poistetaan
...
käytöstä.
...
Tällöin
...
on
...
huolehdittava
...
siitä,
...
että
...
rajapintaan
...
vasten
...
olevat
...
käyttöliittymät
...
ja
...
integraatiot
...
eivät
...
rikkoudu
...
ja
...
että
...
niiden
...
päivittäminen
...
voidaan
...
tehdä
...
hallitusti.
...
J2EE:ssä
...
ei
...
ole
...
mahdollisuutta
...
versioida
...
pakkauksia
...
siten,
...
että
...
niitä
...
voitaisiin
...
ajaa
...
samanaikaisesti
...
muuten
...
kuin
...
pakkausten
...
nimeä
...
muuttamalla.
...
2.4.2
...
Peppi-arkkitehtuurissa
...
käytettävä
...
ratkaisu
...
rajapintojen
...
tekemiseen
...
Sisäisten
...
rakenteiden
...
näkyminen
...
rajapinnassa
...
Peppi-projektin
...
yhteydessä
...
on
...
tehty
...
Kuali-moduulien
...
selvitystyötä
...
sekä
...
havaittu
...
tiettyjen
...
Kualissa
...
käytettävien
...
ratkaisumallien
...
olevan
...
hyödyllisiä
...
Peppi-arkkitehtuurissa.
...
Seuraavaksi
...
on
...
käyty
...
esimerkinomaisesti
...
läpi
...
Kuali
...
Student
...
-moduulin
...
rajapintojen
...
toteutus
...
sekä
...
arvioitu
...
ratkaisumalleja
...
käytettäväksi
...
Peppi-arkkitehtuurissa.
...
Kuali Student -projektin
...
rajapintojen
...
toteutus
...
Rajapinta
LuService-rajapinta
...
sijaitsee
...
ks-lum-api/src/main/java
...
kansiossa
...
org.kuali.student.lum.lu.service
...
pakkauksessa.
...
Rajapinta
...
huolehtii
...
learning
...
unit
...
-olioihin,
...
esimerkiksi
...
opintojakso,
...
liittyvistä
...
toiminnoista.
...
Rajapinta
...
sisältää
...
esimerkiksi
...
seuraavan
...
opintojakson
...
perustiedot
...
palauttavan
...
metodin.
Code Block |
---|
{code} /** * Retrieves core information about a CLU * @param cluId identifier of the CLU * @return information about a CLU * @throws DoesNotExistException cluId not found * @throws InvalidParameterException invalid cluId * @throws MissingParameterException missing cluId * @throws OperationFailedException unable to complete request */ public CluInfo getClu(@WebParam(name="cluId")String cluId) throws DoesNotExistException, InvalidParameterException, MissingParameterException, OperationFailedException; {code} |
Metodi
...
palauttaa
...
DTO-olion(
...
org.kuali.student.lum.lu.dto.CluInfo
...
),
...
joka
...
sijaitsee
...
ks-lum-api/src/main/java
...
kansiossa
...
org.kuali.student.lum.lu.dto
...
pakkauksessa.
...
Toteutus
Clu-luokka
...
(canonical
...
learning
...
unit,
...
joka
...
kuvaa
...
esimerkiksi
...
opintojaksoa)
...
on
...
JPA-tekniikan
...
avulla
...
tehty
...
rakenneluokka,
...
jonka
...
avulla
...
tiedot
...
voidaan
...
tallentaa
...
tietokantaan.
...
Se
...
sijaitsee
...
ks-lum-impl/src/main/java
...
kansiossa
...
org.kuali.student.lum.lu.entity
...
pakkauksessa.
...
LuServiceImpl
...
toteuttaa
...
LuService-rajapinnan
...
ja
...
sijaitsee
...
org.kuali.student.lum.lu.service.impl
...
pakkauksessa.
...
LuServiceImpl
...
luokka
...
sisältää
...
myös
...
JAX-WS
...
annotaatiot,
...
jotta
...
samaa
...
luokkaa
...
käytetään
...
webservice-endpoint
...
luokkana.
Code Block |
---|
} @WebService(endpointInterface = "org.kuali.student.lum.lu.service.LuService", serviceName = "LuService", portName = "LuService", targetNamespace = "http://student.kuali.org/wsdl/lu") @Transactional(noRollbackFor={DoesNotExistException.class},rollbackFor={Throwable.class}) public class LuServiceImpl implements LuService { {code} Rajapinnassa käytettävät rakenteet on eristetty |
Rajapinnassa käytettävät rakenteet on eristetty DTO-olion
...
avulla
...
persistoitavasta
...
Clu-oliosta
...
siten
...
että
...
käytetään
...
LuServiceAssembler
...
luokkaa
...
muuttamaan
...
moduulin
...
sisäinen
...
Clu-olio
...
rajapinnassa
...
käytettäväksi
...
CluInfo-olioksi.
...
getClu
...
metodin
...
toteutus:
Code Block |
---|
{code} @Override public CluInfo getClu(String cluId) throws DoesNotExistException, InvalidParameterException, MissingParameterException, OperationFailedException { checkForMissingParameter(cluId, "cluId"); Clu clu = luDao.fetch(Clu.class, cluId); return LuServiceAssembler.toCluInfo(clu); } {code} |
Assembler
...
muuttaa
...
olion
...
toiseksi
...
toCluInfo
...
-
...
metodin
...
avulla
Code Block |
---|
} public static CluInfo toCluInfo(Clu entity) { if (entity == null) { return null; } CluInfo dto = new CluInfo(); // copy all simple fields - exclude complex data types BeanUtils.copyProperties(entity, dto, new String[] { "officialIdentifier", "alternateIdentifiers", "descr", "participatingOrgs", "primaryInstructor", "instructors", "stdDuration", "luCodes", "credit", "offeredAtpTypes", "fee", "accounting", "intensity", "campusLocationList", "accreditationList", "adminOrgs", "attributes", "metaInfo", "versionInfo" }); dto.setOfficialIdentifier(toCluIdentifierInfo(entity .getOfficialIdentifier())); dto.setAlternateIdentifiers(toCluIdentifierInfos(entity .getAlternateIdentifiers())); dto.setDescr(toRichTextInfo(entity.getDescr())); // accreditingOrg Deprecated in v 1.0-rc2 Replaced by Primary and // Alternate admin orgs dto.setAccreditations(toAccreditationInfos(entity.getAccreditations())); dto.setAdminOrgs(toCluAdminOrgInfos(entity .getAdminOrgs())); dto.setPrimaryInstructor(toCluInstructorInfo(entity .getPrimaryInstructor())); dto.setInstructors(toCluInstructorInfos(entity.getInstructors())); dto.setStdDuration(toTimeAmountInfo(entity.getStdDuration())); dto.setLuCodes(toLuCodeInfos(entity.getLuCodes())); if (entity.getOfferedAtpTypes() != null) { List<String> offeredAtpTypes = new ArrayList<String>(entity .getOfferedAtpTypes().size()); for (CluAtpTypeKey key : entity.getOfferedAtpTypes()) { offeredAtpTypes.add(key.getAtpTypeKey()); } dto.setOfferedAtpTypes(offeredAtpTypes); } dto.setFeeInfo(toCluFeeInfo(entity.getFee())); dto.setAccountingInfo(toCluAccountingInfo(entity.getAccounting())); dto.setAttributes(toAttributeMap(entity.getAttributes())); dto.setMetaInfo(toMetaInfo(entity.getMeta(), entity.getVersionNumber())); dto.setType(entity.getLuType().getId()); if (entity.getCampusLocations() != null) { List<String> campusLocations = new ArrayList<String>(entity .getCampusLocations().size()); for (CluCampusLocation cluCamp : entity.getCampusLocations()) { campusLocations.add(cluCamp.getCampusLocation()); } dto.setCampusLocations(campusLocations); } dto.setIntensity(toAmountInfo(entity.getIntensity())); dto.setVersionInfo(toVersionInfo(entity.getVersion())); return dto; } {code} |
Kuten
...
tästä
...
metodista
...
voi
...
nähdä
...
entity-olio
...
ja
...
rajapinnassa
...
julkaistu
...
Dta-olio
...
sisältävät
...
samat
...
attribuutit
...
ja
...
operaatio
...
tuntuu
...
tarpeettoman
...
monimutkaiselta.
...
Tämä
...
on
...
kuitenkin
...
keino
...
SOA-arkkitehtuurissa
...
huolehtia
...
siitä,
...
että
...
julkaistu
...
rajapinta
...
ei
...
muuttuisi.
...
Toteutus
...
käyttää
...
Apachen
...
BeanUtils-kirjastoa
...
helpottamaan
...
tietojen
...
kopiointia
...
dto-olioon.
...
Yhteenveto Kuali Student -projetissa
...
käytettävälle
...
ratkaisulle
...
Hyötyjä
...
DTO-suunnittelumallissa
...
ovat:
...
- Julkaistu
...
- rajapinta
...
- saadaan
...
- eristettyä
...
- moduulin
...
- sisäisitä
...
- rakenteista
...
- ja
...
- palvelun
...
- kehittämiselle
...
- jää
...
- pelivaraa
...
- Voidaan
...
- optimoida
...
- julkaistua
...
- rajapintaa,
...
- kaikki
...
- tallennettuja
...
- tietoja
...
- ei
...
- välttämättä
...
- tarvitse
...
- siirtää
...
- Voidaan
...
- tehdä
...
- toinen
...
- "näkymä",
...
- toinen
...
- julkinen
...
- rajapinta,
...
- joka
...
- käyttää
...
- eri
...
- dto-olioita
...
Heikkouksia:
...
- Lisää
...
- palvelun
...
- monimutkaisuutta
...
- ja
...
- tietoja
...
- täytyy
...
- muuttaa
...
- useampaan
...
- paikkaan.
...
Peppi-arkkitehtuurissa
...
käytettävä
...
ratkaisu
...
Ratkaisumallina
...
noudatetaan
...
Kuali
...
Student-projektissa
...
esitettyä
...
tapaa,
...
rajapinnat
...
eristetään
...
moduulin
...
sisäisistä
...
rakenteista
...
DTO-suunnittelumallin
...
avulla
...
.
...
Rajapinnat
...
tehdään
...
omiin
...
pakkauksiin
...
moduulikohtaisesti.
...
Dto-olioiden
...
rakentamisessa
...
hyödynnetään
...
BeanUtils-kirjastoa
...
kuten
...
Kuali
...
student
...
-projektissa.
...
Toinen
...
tapa
...
rakentaa
...
Dto-oliot
...
on
...
käyttää
...
Builder-mallia.
...
Tässä
...
mallissa
...
Dto-luokka
...
sisältää
...
staattisen
...
Builder-luokan
...
joka
...
palauttaa
...
Dto-olion.
Code Block |
---|
} public class CourseunitDto implements Serializable { private String name; //setters and getters private CourseunitDto() {} public static class Builder { private CourseunitDto courseunitDto; Builder() { this.courseunitDto = new CourseunitDto(); } public Builder name(String name) { if (name == null) { throw new IllegalArgumentException("Course should have a name"); } this.courseunitDto.setName(name); return this; } public CourseunitDto build() { return this.courseunitDto; } } } {code} {color:#000000}Tällöin |
Tällöin dto-olio
...
voidaan
...
rakentaa
...
seuraavasti.
Code Block |
---|
{color} {code} new CourseunitDto.Builder.name("test").build(); {code} h2. Taaksepäin yhteensopivuus Käytetään |
Taaksepäin yhteensopivuus
Käytetään OSGI-teknologiaa
...
tehdään
...
palvelut
...
OSGI-bundleina,
...
joita
...
ajetaan
...
Servicemix4-alustassa.
...
OSGI
...
mahdollistaa
...
jar-pakkauksen(OSGI-bundle)
...
eri
...
versioiden
...
ajamisen
...
rinnakkain.