Rutinebeskrivelser for utvikling

Denne siden beskriver rutiner for utvikling av FSWS og FS-API (både Web Service- og databasekode).

Forholdet mellom Webservice og databaser

Miljøer

Bruk av GIT

FSWS-DB

Problemer i koblingen Webservice - database

Testing av integrasjoner

Release/deployment

Troubleshooting

Bruk av RT og Jira - saksgang mellom utvikling og forvaltning

 

Forholdet mellom Webservice og databaser

Webservicene for FSWS baserer seg både på direkte SQL og prosedyrekall. En god del spørringer er direkte SQL der man går direkte på tabellene i FS og sammenstiller dataene på serversiden før de returneres. En del andre spørringer kaller opp PL/SQL-prosedyrer som sammenstiller dataene i databasen før de sendes gjennom webservicen. Vi har satt som regel at alle kall på å skrive til databasen går via prosedyrekall.

Miljøer

Vi opererer med tre miljøer i FSWS:

  • Utv: FSUTV + w3utv-jb01.uio.no
  • Test: FS Demo + jboss-test.uio.no (w3test0N.uio.no)
  • Prod: FS Prod + fsws.usit.no (w3prod0N.uio.no)

Utviklingsmiljøet har vi full kontroll over via SQL*Plus/SQL Developer/Toad og JBoss Management-konsoll.

De to andre miljøene administreres av Drift (www-drift for applikasjon og oracle-drift for database).

Bruk av GIT

Generelt

All koden til FSWS ligger i GIT, under FS-prosjektet. Følgende kode finnes:

  • fsws-db: PL/SQL-kode og tabelldefinisjoner for FSWS
  • fsws-core: Felles kode for alle webservices
  • fsws-rest: Kode for REST-webservice
  • fsws-soap: Kode for SOAP-webservice
  • fsws-intern: Kode for intern-webservice, en proxy-tjeneste som databasen bruker for å sende data 

Vi strever etter å følge GIT-flow mønsteret for utvikling, men det hender ting glipper. Minimumskravet er dette:

  1. Master-branch skal aldri røres. Her skal det kun ligge releaseversjoner.
  2. Develop-branch skal være konsistent, stabil og kompilerbar. Koden som ligger i develop må ikke til en hver tid være perfekt og releasebar (selv om det er en fordel!), men det må kunne kompileres slik at ikke kode som ender i develop stopper andres utvikling.
  3. Kode under utvikling/testing ligger i brancher.

Mer detaljert bruk av Git kommer i eget dokument. Ellers finnes det masser av eksempler på nett.

Bruk av Git-branches

De fleste prosjektene benytter seg av en "develop" branch for å sikre seg at ting ikke sjekkes inn i master. I tillegg så tar man ofte i bruk egne branches for å utvikle. Her er et eksempel på bruk:

Trinn 1: Opprette branch fra Jira

Utdrag fra Git-kommandolinje:

richared@USIT93-59 /c/git/demo (master)
$ git pull
From ssh://utv.uio.no:7999/fs/demo
 * [new branch]      bugfix/FSWS-1055-sak-for-a-demonstrere-branching -> origin/bugfix/FSWS-1055-sak-for-a-demonstrere-branching
Already up-to-date.

Her ser man at ny branch er hentet ned. Nå bytter vi til denne branchen for å jobbe med den:

richared@USIT93-59 /c/git/demo (master)
$ git checkout bugfix/FSWS-1055-sak-for-a-demonstrere-branching
Branch bugfix/FSWS-1055-sak-for-a-demonstrere-branching set up to track remote branch bugfix/FSWS-1055-sak-for-a-demonstrere-branching from origin.
Switched to a new branch 'bugfix/FSWS-1055-sak-for-a-demonstrere-branching'

OBS OBS! Husk at man må sjekke inn på branch før man eventuelt bytter til en annen branch. Se her:

 

Gjør endringer og sjekk inn... Resten av jobben gjøres i Stash:

Vi lager derfor en Pull request:

FSWS-DB

Struktur på databasekoden

Databasekoden for FSWS er trukket ut av FS-koden for øvrig, og lagt i eget repo fsws-db (under fs). Her er det laget kopier av alle aktuelle underkataloger, slik at strukturen i FS-repoet (db) er bevart (i hvert fall inntil videre). I tillegg er det lagt til noe:

  • FS
    • PROG (pakker)
    • VPD (VPD-policies)
  • FSSYS (temp.tabeller)
  • REPORT (rapporter)
  • scripts (Python-script for generering av release)

Foreløpig deployes koden til FS-skjemaet, men på sikt er det ønskelig med egne skjemaer som gjenspeiler repo-strukturen.

Retningslinjer for klientoppsett

Det er flere måter å kjøre SQL på (SQL*Plus, Toad, SQL Developer) som har forskjellig oppsett. I den grad det er mulig i det enkelte verktøy, anbefales det å kjøre med noen form for warnings, for å sikre best mulig kodekvalitet.

SQL*Plus (lokalt eller på fs-patch01)

Verktøyet opererer med en init-fil login.sql, som må ligge i katalogen man starter fra (hvis man kjører fra flere kataloger, anbefales det å ha én sentral init-fil som de katalogspesifikke filene starter opp).

Datoformat og kompilator-flagg

-- Default er DD-MON-YY i DOS-versjonen av SQL*Plus
alter session set NLS_DATE_FORMAT = 'DD.MM.YYYY'
/

-- PL/SQL-kompilatoren har en rekke warnings, men i praksis gir noen av dem for mange varsler, så disse anbefales disablet:

alter session set PLSQL_WARNINGS  = 'ENABLE:ALL', 'DISABLE:7202', 'DISABLE:7204', 'DISABLE:5018'
/
alter session set PLSCOPE_SETTINGS= 'IDENTIFIERS:ALL'
/

Server-output

set termout off
exec dbms_output.enable
set termout on
set serveroutput on size 1000000

-- Fjerner trailing blanks (pga. linesize)
set trimspool on

SQL*Plus prompt

For å unngå å jobbe i feil skjema/database (og i verste fall rote det til i Prod!), er det anbefalt å sette opp SQL*Plus-prompten til å vise skjema/database man til enhver tid er logget inn i (default er "SQL> "). Skjema hentes fra USER_USERS og database fra GLOBAL_NAME, mens et SQL*Plus-triks sørger for at resultatet av en SELECT havner i ønsket SQL*Plus-variabel (SQLPROMPT):

set verify    off
set heading   off
set feedback  off

define new_prompt='***'
column prval new_value new_prompt

select <Uttrykk på USERNAME og GLOBAL_NAME> prval
  from
       USER_USERS,
       GLOBAL_NAME
 where
       1=1
/
set sqlprompt "new_prompt"
set verify    on
set heading   on
set feedback  on

Toad (lokalt)

<Anbefalte settinger>

SQL Developer (lokalt)

<Anbefalte settinger>

Retningslinjer for programmering (best practices)

Modularisering og ytelse står ofte mot hverandre i databaseprogrammering. Når ytelse er et issue (som det ofte er i integrasjonssammenheng) er det noen ting man må unngå:

1) Generelt: Funksjoner som kalles fra SQL, og i sin tur utfører egen SQL (optimizeren klarer ikke å resonnere)

2) XML-spesifikt: SELECT XMLElement (...) FROM Dual; på detaljnivå (dvs. der denne kalles mange ganger)

Dette betyr at man går glipp av en del modulariseringsmuligheter, og typisk må duplisere funksjonalitet inline i aktuelle SQL. F.eks. gjør 1) at man ikke kan bruke FS-funksjoner som gjør egne spørringer på detaljnivå hvis hovedspørringen behandler store datamengder. Årsaken til at 2) kan være ønskelig, er at SQL/XML (XMLElement osv) kun kan kalles i en spørring: Hvis man ønsker å generere et XML-element for en enkelt forekomst, må man gjøre det i en spørring som returnerer en enkelt rad (noe som typisk gjøres fra Dual).

Det finnes dog en annen mekanisme som gir en viss mulighet for modularisering uten å bruke funksjoner: Subquery factoring. Man kan angi en eller flere navngitte delspørringer foran hovedspørringen, som kan brukes i sistnevnte:

WITH q1 AS (SELECT ...), q2 AS (SELECT ...), ...

SELECT ... q1 ... q2 ... ;

NB! Faktoriserte subspørringer gir opphav til "temporary tables", noe som kan gi dårlig ytelse hvis datasettet er for stort.

Problemer i koblingen Webservice - database

Når webservicene kaller prosedyrer i databasen så skjer dette ved at man i webservice-koden definerer navnet på metoden man vil kalle og med hvor mange parametere. Deretter gjøres det JDBC-kall mot databasen med riktig metodesignatur. Dette fører til et vesentlig problem: Fordi databasekoden og webservice-koden ikke er direkte linket, vil ikke endringer i grensesnittene i databasen automatisk gi utslag i webservicen - før det er for seint (dvs. når koden brekker). Altså: Dersom man enten endrer på kallet i webservicen eller grensesnittene i databasen uten at de to er synkronisert, vil webservice-kallene feile. I tillegg har man nok et problem: FS kjører på flere baser - derfor rulles ikke databasekoden ut samtidig til alle baser. Webservicen, derimot, kjører mot alle baser samtidig og kan derfor kalle både nye og gamle grensesnitt samtidig. Altså: Når man endrer et grensesnitt i databasen, så vil webservicen måtte håndtere både nytt kall-grensesnitt og gammelt kall-grensesnitt samtidig.

For å bøte på disse problemene har vi definert følgende operasjonsmodus når man vil endre på et kallgrensesnitt i basen, f.eks. ved å legge på et nytt felt:

  • 1: Opprett det nye grensesnittet i PK_FSWS. NB! Ikke slett det gamle grensesnittet (m.a.o. bruk overloading).
  • 2: Endre metoden i pakken som PK_FSWS kaller på.
  • 3: Det gamle grensesnittet i PK_FSWS settes til å kalle på det nye grensesnittet.
  • 4: Databasekoden deployes med disse endringene. Webservicen vil fortsatt gå mot gammelt grensesnitt, men dette delegerer videre til nytt. Ingenting feiler fordi alle metodene finnes.
  • 5: Når databasekoden er rullet ut til alle baser kan man oppdatere webservicen til å kalle på det nye grensesnittet i PK_FSWS.
  • 6: Webservicen deployes og vil nå virke mot nytt grensesnitt
  • 7: Det gamle grensesnittet kan nå trygt fjernes fra PK_FSWS

Merk at denne omstendelige prosessen er ikke nødvendig dersom man bare endrer innholdet i en prosedyre, kun dersom man endrer på metodesignaturen (dvs. ved å legge til, fjerne eller endre parametere - evt. endre returtype).

Testing av integrasjoner

Testing av Webservice

Ved feilsøk kan det være nyttig å teste databasedelen for seg, noe som gjøres ved å kalle toppfunksjonen for den aktuelle webservicen direkte i SQL*Plus, Toad el.lign.

Når det gjelder testing av hele stacken (database + applikasjon) finnes det flere verktøy:

  • SOAP: SOAP-UI
  • REST: Advanced REST Client
  • REST: Browser
  • REST: Java-kode
  • REST: Jenkins

Testing av REST med Javakode

I fsws-rest koden er det laget egne pakker med testkode, ligger under src/java/test. Disse kan kjøres i Eclipse. Åpne koden i Eclipse og høyreklikk på koden og velg "Run as" -> "JUnit Test".

Denne vil da kjøre koden og avgi rapport:

Dette kommer til å komme i Jenkins etterhvert som en natt-jobb.

Testing av overføring fra database

LMS

Databasedelen testes (for institusjonsnr nnnn) ved å kalle den aktuelle topprutinen (logget inn som Innnn_FS_WS):

  • Fronter (alle parametere er valgfri):
    • U/overføring: select FS.PK_FSWS_LMS.F_Fronter (LMSLopenr, Session_ID)
    • M/overføring: exec FS.PK_FSWS_LMS.P_FronterEksport (LMSLopenr, Session_ID)
  • Itslearning (alle parametere er valgfri):
    • U/overføring / Full eksport : exec FS.PK_FSWS_LMS_ITSL.P_Full_Eksport (1, Session_ID, LMSLopenr)
    • M/overføring / Full eksport : exec FS.PK_FSWS_LMS_ITSL.P_Full_Eksport (0, Session_ID, LMSLopenr)
    • U/overføring / Inkr. eksport: exec FS.PK_FSWS_LMS_ITSL.P_Inkrementell_Eksport (1, Session_ID, LMSLopenr)
    • M/overføring / Inkr. eksport: exec FS.PK_FSWS_LMS_ITSL.P_Inkrementell_Eksport (0, Session_ID, LMSLopenr)
  • Parametere:
    • LMSLopenr (default NULL begrenser ikke på LMSLopenr i kildetabeller)
    • Session_ID (default: genereres av systemet)

Release/deployment

Applikasjon

Deployment i Utv (w3utv-jb01.uio.no)

JBoss Management-konsoll:

  • Domain/Overview
    • Stopp fsws-1
  • Deployments
    • Velg fsws.war
    • Replace
  • Domain/Overview
    • Start fsws.war

Deployment i Test (jboss-test.uio.no) eller Prod (fsws.usit.no)

WinSCP w3utv-jb01:

  • Gå til ...\workspace\target (lokalt) og /tmp (remote)
  • Overfør fsws-N.N.N.war

Be www-drift (RT) deploye den overførte fila.

Release

********************* Fyll ut *********************

Database

Deployment

Kompilering

Deployment av (endringer i) databasekode består av innlogging på det aktuelle FS-skjemaet og kompilering (kjøring av aktuell pakkekode fra fil):

  • I Utv (FSUTV) og Demo (FS0nDMO / FSDEMO) kan dette gjøres fra klientsiden via SQL*Plus, Toad el.lign, da databaseutviklere som regel har direkte tilgang til disse miljøene
  • I Prod (FS0nPRD / FSPROD) må dette normalt (dvs. hvis man ikke heter Geir eller Kari) gjøres via SQL*Plus på fs-patch01.

I utgangspunktet er det å foretrekke å kompilere ifm. nedetid, for ikke å påvirke evt. lange sesjoner som bruker den aktuelle koden. Dette gjelder en midlertidig og en permanent problemstilling:

  • Den midlertidige er en databasebug som gjør at sesjonene risikerer å gå i spinn, og etterhvert få basen til å knele
  • Den permanente er at sesjonene feiler ved de(t) første kallet (kallene) pga. forkastet tilstand i pakkevariable
Hvis kompilering gjøres mens basen er oppe
  • Avklar hvilke apper som berøres av endringen
    • Integrasjon (FSWS, FS-API)
    • WebApp (StudentWeb, SøknadsWeb, FagpersonWeb...)
  • FSWS, FS-API (flere?): Sperr tjenesten(e)
  • Midlertidig: ​Synkroniser med oracle-drift: Overvåkning om X (+)
  • WebApp: Logg på alle baser
  • Vente X (+)
  • FSWS: ​Flush
  • Deploy i aktuelle baser
  • Rekompiler evt. ugyldige objekter - automatisk?
  • FSWS, WebApp: Flushe connections (+ cache?) for aktuelle applikasjoner
    • Gjøres i Rundeck
      • Først StudentWeb
      • Deretter apper som brukes sjeldnere
    • Hvis feilmeldinger ikke opphører:
      • Prøv igjen
      • Varsle www-drift (det er ikke alltid flush fungerer)
  • WebApp:
    • Søk (++) etter feilmeldinger i translogger i alle baser:
      • StudentWeb: SW3S_TRANSLOG
      • SøknadsWeb: SOWS_TRANSLOG
      • EVUWeb: EVUWEB_TRANSLOG
    • Sjekk om feilmeldingene opphører etter flushing
    • Hvis ikke: Flush igjen + Send hastemelding til www-drift (TEKST?)
  • FSWS: ​Flush igjen
  • ​Åpne tjenesten(e) igjen

(+) Tiden det tar før tjenesten er stengt (om mulig):

  • FSWS  : 30 min
  • FS-API: 2 timer
  • WebApp: ?

(++) Spørringer mot translogger:

select procnavn, merknad_feil, Count(*)
  from &translog -- En av loggtabellene over
 where merknad_feil is not null
   and sessiondate > sysdate - 1
 group by procnavn, merknad_feil
/
select Max(sessiondate), sysdate
  from &translog -- En av loggtabellene over
 where merknad_feil is not null
   and sessiondate > sysdate - 1
/

Release

For release av nye versjoner (vs. deployment av enkeltendringer) benyttes et Python-script:

scripts/build.py

Her kan man angi hvilken forrige release man ønsker å generere endringer siden (default er forrige release).

Troubleshooting

SoapUI

Det hender verktøyet cacher resultatet (t.o.m. ved parameterendringer!) - noe som kan vise seg ved uventet kort eksekveringstid og samme resultat som forrige request (der dette ikke er forventet). I så fall må man restarte klienten.

Feilmeldinger

ORA-64451: Conversion of special character to escaped character failed

  • Årsak: Det forekommer kontrolltegn i dataene (typisk navn, adresse, merknadsfelt, URL...) - som regel pga. copy/paste fra Word el.lign.
  • Quick fix: Kjør mistenkte delspørringer rad for rad (sortert) til feilen gjenskapes, og be institusjonen rette opp de aktuelle feltene
  • Varig løsning: Få FS (database og/eller klient) til å forhindre slike verdier fra å bli lagres i fremtiden

ORA-28112: failed to execute policy function / ORA-28113: policy predicate has error

Betyr at en VPD-policy feiler. Disse er standard feilmeldinger som skjuler en bakenforliggende feil som i utgangspunktet ikke vises. Hvis man ikke finner årsaken ved kodeinspeksjon eller trace, må man be Drift om feilloggen fra databasen (udump-katalogen), der den bakenforliggende feilmeldingen vises.

ORA-12170: TNS: Det oppstod et tidsavbrudd for tilkoblingen

Kommer som regel av at man ikke slipper igjennom en brannmur.

No more data to read from socket

  • Årsak: Dette er som regel noe på driftsnivå (applikasjonen er nede, feil i databasepeker, ...)
  • Løsning: Restart av applikasjonen, rettelse av databasepeker, ...

Timeout

Det hender applikasjonsserveren eller webserveren avbryter et webservice-kall fordi det ikke avsluttes i løpet av den tidsgrensen som er angitt på serveren. Denne grensen kan variere (Drift ønsker typisk max 3 min, men vi har noen ganger bedt om det dobbelte eller mer i et begrenset tidsrom). Det første man bør gjøre er å avgjøre om problemet er på database- eller applikasjonsnivå, ved å kjøre kallet direkte i databasen. Hvis det går ut over timeout-grensen, blir det en tuning-jobb. Hvis ikke, er problemet på enten webserver- eller applikasjonsserver-nivå - med varierende løsningsforslag:

Webserver (Apache):

  • Flush av cache
  • Restart av server

Applikasjonsserver (JBoss):

  • Restart av server

Bruk av RT og Jira - saksgang mellom utvikling og forvaltning

Flytskjema

Publisert 1. sep. 2015 15:15 - Sist endret 29. mars 2022 09:36