Videregående programmering i Java

Dag 13 - valgfrie emner

Evt: Introduktion til J2EE og EJB

Hvordan definere egne generics

Evt.: Værktøjer til forbedring af kodekvalitet - kodemetrikker og audit

Projektvejledning

Udgår: Introduktion til J2ME, midletter og programmering af mobiltelefoner

Læsning: Evt VP 14 (VP 13 udgår)

Dette materiale er under Åben Dokumentlicens, se http://www.sslug.dk/linuxbog/licens.html

Sidste gang - spørgsmål?

Dag 12 - Introspektion og optimering

Introspektion af klasser på køretidspunktet (reflektion)

Evt.: JAR-filer og oprettelse af eksekverbare JAR-filer

Optimering af programmer

Evt.: Optimeringsværktøjer (Borland OptimizeIt)

Projektvejledning

Læsning: VP 9, VP 11

Java 2 Enterprise Edition (J2EE)
- til store servere

J2EE-platformens dele

Webserver

EJB (Enterprise JavaBeans)

CORBA - fjernkald af objekter (ikke kun Java, sværere end RMI)

JTS (Java Transaction Service) - transaktioner (commit, rollback)

JMS (Java Message Service) - til MQ-systemer.

tjeneste til at sende og modtage synkrone eller asynkrone meddelelser mellem programmer

JavaMail, XML-behandling, ...

Sun varetager 'kun' J2EE-specifikationen

Mange uafhængige udbydere af J2EE-platforme

Borland AppServer

Oracle

IBM WebbSphere

JBoss (med åben kildekode)

Sun (referenceimplementation)

... (>10 andre)

J2EE != udviklingsplatform

Mange udbydere har også egen, 'strømlinet' webudviklingsmodel

Enterprise JavaBeans (EJB)
- objekter i serveren

J2EE-container varetager EJB-objekter

Persistens, transaktioner, sikkerhed

Kald kan ske lokalt eller over netværket

F.eks. fra JSP-sider!

EJB koncentrerer sig om programlogik

Serveren sørger for al 'benarbejdet'

Sessionsbønner repræsenterer et forløb

Entitetsbønner repræsenterer data fra en tabel

Containerstyret persistens (CMP)

Al databasekode bliver genereret af containeren (!)

Bønnestyret persistens (BMP)

Programmøren skriver selv databasekoden

Meddelelses-drevne bønner

Princippet i kald af metoder i
objekter over netværket

En EJB-bønne kører en en J2EE-applikationsserver - muligvis adskilt fra klienten

Hver EJB-bønne udgøres af tre stykker kildetekst (to interfaces og en klasse):

1)Et fjerninterface (eng.: remote interface), der specificerer hvordan bønnen kan bruges af klienten.

2)Et hjemmeinterface (eng.: home interface), der specificerer, hvordan bønnen kan fremfindes, oprettes og nedlægges af klienten.

3)En implementationsklasse af bønnen, med den programkode, der beskriver, hvad der skal ske, når de forskellige metoder i fjerninterfacet kaldes.

Kildekoden i en EJB

... plus noget information til EJB-containeren (XML)

Bruge en EJB

Typer af EJB

Sessionsbønner

repræsenterer et eller andet forløb og indeholder de data der knytter sig til dette forløb

Tilstandsløse (eksempel: Veksler-bønnen)

Flere klienter kan dele samme instans

Tilstandsfulde

Hver klient får sin egen instans

Entitetsbønner

repræsenterer data fra en tabel. De er persistente
(dvs. deres data 'bakkes op' af en database).

Containerstyret persistens (CMP)

Al databasekode bliver genereret af containeren (!)

Bønnestyret persistens (BMP)

Programmøren skriver selv databasekoden

Meddelelses-drevne bønner

Entitetsbønner med CMP

EJB Query Language

EJB Query Language

EJB: Transaktioner

Programmatisk ('i hånden'-) transaktionsstyring

Deklarativ transaktionsstyring

Metoder markeres med en transaktions-attribut

Det er containerens opgave at sørge for at oprette, nedlægge, fuldføre og evt. annullere transaktioner i henhold til disse

Required - metoden er med i den aktuelle transaktion.

Der oprettes en ny transaktion af containeren, hvis der ikke er nogen i gang.

Supports - metoden er med i den aktuelle transaktion.

Der oprettes ikke en ny transaktion af containeren, hvis der ikke er nogen i gang.

Mandatory - metoden skal være med en transaktion.

Er der ikke er nogen i gang, kastes undtagelsen TransactionRequiredException.

Never - metoden må aldrig være med en transaktion.

Er der en transaktion i gang, kastes undtagelsen RemoteException af containeren.

RequiresNew - der oprettes en ny transaktion.

Hvis der er en transaktion i gang, suspenderes denne indtil metoden har afsluttet.

NotSupported - kan ikke være med en transaktion.

Hvis der er en transaktion i gang, suspenderes indtil metoden har afsluttet.

Værktøj til forbedring af kodekvalitet – automatisk koderevision (audit)

Nogle værktøjer (JBuilder, JDeveloper, ...) kan søge programkoden igennem og revidere den (eng.: audit)

Består af 30-80 forskellige tjek af koden på forskellig måde

Almindelige fejl og uhensigsmæssigheder påpeges

Griber ind i programmørens kodningsvaner

Nok nødvendigt i projekter med mange programmører

Hvilke tjek der skal foretages kan indstilles fra projekt til projekt

Eksempel:

Use Abbreviated Assignment Operator (UAAO)

Use the abbreviated assignment operator in order to write programs more rapidly. Also some compilers run faster when you do so.

Wrong

void oper () {

int i = 0;

i = i + 20;

i = 30 * i;

}

Right

void oper () {

int i = 0;

i += 20;

i *= 30;

}

Andre eksempler:

'switch' Statement Should Include a Default Case (SSSIDC)

Assignments to 'for' Loop Variables (AFLV)

Accessing Static Members through Objects (ASMO)

Assignments to Formal Parameters (AFP)

Versionskontrol

Hvordan arbejde sammen i større grupper?

Systemer

CVS (Åben kildekode)

Subversion (Åben kildekode)

ClearCase

StarTeam

Visual SourceSafe (Microsoft)

Demo af CVS

Definere egne generiske klasser

Parametriserede klasser/generiske typer = erklæring af en klasse med en eller flere klasser som parametre

~= templates fra C++

Fordele

Klarere kode

Typesikkerhed

Hvordan

Ved 'type erasure' – typerne erstattes bare med 'Object' efter oversættelse og typetjek (til forskel fra templates i C++)

Derfor er formålet med generiske klasser:

Programmøren skal altid advares under oversættelsen hvis der er risiko for en tildeling af en forkert type objekt til en variabel (ClassCastException)

Definere egne generiske klasser

package generisk;

import java.awt.*;

/** En klasse til a gemme info om et andet objekt */

public class Info<O>

{

public O obj;

public String txt;

public Info(O objp, String txtp) {

obj = objp;

txt = txtp;

}

public String toString() {

return "INFO "+obj.toString()+" "+txt;

}

public static void main(String[] args)

{

Info<Point> info = new Info<Point>(new Point(), "origo");

System.out.println(info);

// udskriver: INFO java.awt.Point[x=0,y=0] origo

}

}

En generisk Info-klasse

Anbefaling: Brug ét stort bogstav til formelle typeparametre

Definere egne generiske klasser

package generisk;

import java.io.*;

public class Serialisering<T extends Serializable>

{

public void gem(T obj, String filnavn) throws IOException

{

FileOutputStream datastrøm = new FileOutputStream(filnavn);

ObjectOutputStream objektstrøm = new ObjectOutputStream(datastrøm);

objektstrøm.writeObject(obj);

objektstrøm.close();

}

public T hent(String filnavn) throws Exception

{

FileInputStream datastrøm = new FileInputStream(filnavn);

ObjectInputStream objektstrøm = new ObjectInputStream(datastrøm);

Object obj = objektstrøm.readObject();

objektstrøm.close();

return (T) obj;

}

}

En generisk serialiserings-klasse

Parametriseret ved en klasse, der skal være serialiserbar

Klassemetoder/variabler kan ikke parametriseres

Hvorfor? (husk: Vi skal altid advares om risiko for forkerte typer)

package generisk;

import java.util.*;

public class HentOgGem

{

public static void main(String[] arg) throws Exception

{

Serialisering<String> serialiseringStr = new Serialisering<String>();

serialiseringStr.gem("en streng","str.ser");

//Ulovlig: Serialisering<Socket> serialisering3 = new Serialisering<Socket>();

Serialisering<ArrayList<String>> serialiseringALS = new Serialisering<ArrayList<String>>();

ArrayList<String> l;

try {

l = serialiseringALS.hent("venner.ser");

System.out.println("Læst: " + l);

}

catch (Exception e) {

e.printStackTrace();

l = new ArrayList();

l.add("Jacob");

l.add("Brian");

l.add("Preben");

System.out.println("Oprettet: " + l);

}

l.add("Ven" + l.size());

serialiseringALS.gem(l, "venner.ser");

System.out.println("Gemt: " + l);

}

}

Definere egne generiske klasser

Quiz: Kan man det følgende:

List<String> ls = ...

List<Object> lo = ...

ls = lo // nej, vel???

lo = ls // ???

lo.add(new Point()); // hmm...!

Vi skal altid advares om risiko for forkerte typer

Wildcards i definitionen af den generiske klasse

print(List<?> l)

print(List<? extends Shape> l)

Præsentatoner fra kurset Videregående programmering i Java

2004-08-30T12:23:21