Java EE 6 – det med småt

Det er ingen hemmelighed at releaset af Java EE 6 stadig optager os. Nicky Mølholm er dykket ned i specifikationen og har skrevet en artikel om de ændringer, der har med hele platformen at gøre.
De enkelte dele af Java EE 6, som JAX-WS, EJB 3.1, JPA 2.0 etc, er efterhånden blevet grundigt beskrevet og vurderet i diverse artikler, fora og blogs. Nicky angriber platformen fra en anden vinkel i sin artikel, ved at tage fat i tværgående emner som de nye Java EE profiler, pruning i Java EE platformen, classloading, naming environments og deployment af DataSources.
Java Enterprise Edition 6 (aka Java EE 6) blev gjort tilgængelig i december 2009. Den nye udgave af Java EE platformen indeholder en række opdateringer til velkendte teknologier som EJB, Servlets, JCA, JAX-WS og mange andre. Nyhederne i hver af disse konkrete teknologier er efterhånden ved at være afdækket på diverse blogs, fora og nyhedssites. Denne artikel gennemgår de forandringer, der er sket på tværs af alle teknologierne – nemlig dem som er beskrevet i JSR 316 – Java Platform, Enterprise Edition 6 (Final Release):

  • API- og Java SE versioner
  • Pruning
  • Java EE platform profiler
  • Nyheder i applikationskomponenternes naming environment
  • DataSources
  • Class loading

Hver enkelt af de ovenstående emner har stor betydning for de rammer, vi som Java EE 6 udviklere arbejder indenfor. I afsnittet API- og Java SE versioner afdækkes hvilke API versioner der er uberørt, hvilke der er opdaterede og ikke mindst hvilke APIs som er nye i platformen. I Pruning afsnittet kan du læse om en helt ny proces i Java EE platformen som har en ganske stor betydning for hvilke teknologier, der efterhånden vil blive gjort valgfrie. Men een af de største forandringer, som påvirker alle Java EE containertyperne (Web, EJB, osv), er den der er foretaget for applikationskomponenternes naming environments. Husker du java:comp/env namespacet? Nu er der kommet tre nye!

Er du udvikleren eller arkitekten med god, bred forståelse af Java EE platformen som den ser ud i dag, så vil du helt sikkert finde en række spændende nyheder herunder.

API- og Java SE- versioner

I Java EE 5 var det påkrævet, at leverandører understøttede minimum Java SE 5. I Java EE 6 skal leverandører tilsvarende understøtte Java SE 6. En del af de APIs, som tidligere var placeret i Java EE platformen, er nu en integreret del af Java SE, herunder: JAF 1, SAAJ 1.3, og StAX 1.0. Derudover er JDBC 4.0 også en integreret del af Java SE 6 – og altså nu også til rådighed for Java EE 6 udviklere.

Udover de APIs som Java SE 6 indeholder, stiller specifikationen en række krav til ekstra enterprise APIs der skal være i enhver Java EE 6 kompatibel applikationsserver. Nedenstående figur illustrerer hvilke APIs, i hvilke versioner, der skal være tilgængelige på en Java EE 6 server.

Af nye APIs finder du blandt andet JAX-RS 1.1 API’et til udvikling af restful Web services, Bean Validation 1.0 til validering af POJOs i JPA og JSF applikationer, og det vel nok mest skelsættende API: Contexts and Dependency Injection (CDI) for Java EE 1.0, som introducerer elementer kendt fra Spring og Seam, men som samtidigt rykker grænsen med endnu flere innovative features! Blandt de opdaterede APIs findes blandt andet EJB 3.1 med nyheder som no-interface view og singleton session beans, JSF 2.2 som har udskiftet renderingsmotoren med facelets, samt Servlet 3.0 der blandt andet tilbyder asynkrone kald og meget mere.

Pruning

Efterhånden som Java EE 6 platformen har udviklet sig, er en del af de inkluderede teknologier ikke helt så relevante som tidligere. For at kunne håndtere den voksende mængde af efterhånden irrelevante teknologier, introducerer Java EE 6 platformen den såkaldte ’Pruning’ process. Processen består af følgende steps for Java EE ekspert gruppen:

  1. For release N af platformen udvælges en liste af teknologier, som man vil gøre valgfrie i senere releases – de får status: ”proposed removal”.
  2. For release N+1 af platformen gennemgåes listen af proposed removals for at afgøre følgende: om teknologien skal gøres valgfri, forblive i platformen som en påkrævet teknologi, eller om den skal forblive i status ”proposed removal” til senere Java EE releases.

En vigtig pointe i forbindelse med pruning processen er, at teknologier ikke fjernes helt fra Java EE platformen – men derimod gøres valgfri. Leverandører af Java EE kompatible produkter har efterfølgende lov til at ekskludere de valgfrie teknologier.

I Java EE 6 er følgende teknologier markeret som valgfrie til fremtidige Java EE platforme: EJB 2.1 EntityBean komponent modellen, JAX-RPC 1.1, Java EE Deployment 1.2 samt JAXR 1.0.

Java EE platform profiler

Sun introducerer nu mulighed for, at man via Java Community Process (JCP) kan lave specialiserede udgaver af Java EE platformen, kaldet profiler. En Java EE profil udarbejdes i form af en JSR (Java Specification Request) – typisk af en eller flere Java EE produkt leverandører. Alle profiler skal som minimum implementere en fællesmængde af teknologier, herunder naming samt dependency injection af resurser. Derudover er der ret frie hænder til at definere profiler. Eksempelvis har profiler lov til at:

  • Fjerne passende subsets af Java EE platformen
  • Tilføje en eller flere teknologier
  • Bygge videre på en eksisterende Java EE profil
  • Markere teknologier som valgfrie (for produkter baseret på profilen)
    Et oplagt eksempel på en Java EE profil kunne være en hypotetisk Java EE Portal profil. En sådan profil ville sandsynligvis inkludere den fulde Java EE 6 platform, samt relevante Portlet APIs.

Ud over de væsentligste Web teknologier som JSP, Servlets, EL, JSF mv, er det værd at bemærke, at Java EE Web Profile baserede produkter også indeholder en neddroslet udgave af EJB 3.1 stakken (kaldet EJB Lite), JTA (for transaktioner), CDI og JPA – altså specificerer profilen nogle af de væsentligste teknologier, der anvendes i forbindelse med udvikling af moderne forretningskritiske Java EE systemer. Af åbenlyse enterprise teknologi ”mangler” kan nævnes JMS, Web services (JAX-WS / JAX-RS), Java EE Connectors og EJB remoting (gælder både remote klienter og remote services). Hvad angår Java EE modul typer, gælder det endvidere, at det kun er WAR filer der skal understøttes af leverandørerne.

Java EE Web profilen giver altså en alternativ letvægtsplatform for applikationer, der kan realiseres uden “heavy weight” enterprise teknologier. En anden faktor, som kan gøre produkter baseret på web profilen attraktive, er prisen – det er jo ikke utænkeligt, at store leverandører som Oracle, Redhat og IBM en dag vil tilbyde trimmede produkter til en langt lavere pris end deres egentlige Java EE flagskibsprodukter.

Class loading

Java EE 6 specifikationen inkluderer som noget nyt en beskrivelse af kravene til class loading. For hver container type beskrives hvilke klasser og resurser der skal være tilgængelige i classpath for applikationen. Netop formaliseringen af disse krav er et super værktøj til dig som lægger en ære i udvikleportable applikationer. Hvis man eksempelvis skal migrere en applikation fra en JBoss Java EE 6 server til en Oracle WebLogic Java EE 6 server, så bør en af aktionerne være at sørge for at class loading reglerne i dette afsnit er overholdt.

I figuren anvendes begrebet library: Et library i Java EE platformen refererer til en JAR fil med klasser og diverse ressourser. Ved hjælp af META-INF/MANIFEST.MF filen kan man erklære afhængigheder til disse libraries. Libraries kommer i to varianter: ’bundled’ eller ’installed’. Eksempler på bundlede libraries er JAR filer som man lægger i WAR modulers WEB-INF/lib folder og EAR modulers library folder (typisk: ’lib’). Et installeret library er typisk en JAR fil som er præ-installeret i en Java EE server.

Med class loader reglerne for Java EE 6 har vi altså nu fået formaliseret præcis hvilke klasser og resurser vores komponenter kan anvende. Formaliseringen af class loader reglerne er uden tvivl et stort skridt frem. Bemærk dog at man i specifikationen ikke har medtaget konkrete regler for hvordan class loadere skal organiseres i Java EE 6 servere – dette er helt op til server leverandørerne. En konsekvens af dette er at man ikke kan anvende ovenstående regler til at resonere omkring ordenen for loading af diverse klasser. Ønsker man dette så må man, nøjagtigt som er tilfældet i dag, ty til leverandørens produktdokumentation.

Naming environment

En ganske betydelig nyhed er introduktionen af tre nye applikationskomponent namespaces: java:module, java:app, og java:global. Disse udgør nu sammen med java:comp de fire namespaces som er tilgængelige for applikationskomponenter som EJB’ere og Servlets. Som i Java EE 5 kan applikationskomponenterne enten vælge at slå resurser i namespaces op vha JNDI eller at få dem indsat i member variable vha dependency injection (vha annotationer eller fra modulets deployment descriptor).

  • java:comp – Dette namespace var også tilgængeligt for Java EE 5 applikationer. Det er et per-komponent namespace. Eksempelvis kan alle instanser af én EJB se samme namespace – men én EJB kan ikke se en andens namespace. Af historiske årsager afviger Web moduler dog fra dette – her deler alle Web komponenter samme namespace.
  • java:module – Dette namespace deles af alle komponenter i same modul. Eksempelvis kan alle EJB’ere i samme EJB-JAR modul se samme namespace – men EJB’ere i et modul kan ikke se en anden EJB-JARs module namespace. Bemærk, at for Web moduler refererer java:module namespacet til det samme namespace som java:comp.
  • java:app – Dette namespace deles af alle komponenter i samme applikation. En applikation kan være en EAR fil eller et standalone modul som eksempelvis en WAR eller EJB-JAR. Eksempelvis kan EJB’ere fra en EJB-JAR i en EAR fil se samme namespace som Servlets fra en WAR i samme EAR fil – men EJB’ere fra en EAR fil kan ikke se et namespace tilhørende en anden EAR fil.
  • java:global – Dette namespace deles af alle applikationer i en applikationsserver. En applikationserver kan være en enkelt server, et cluster af applikationsservere, et administrativt domæne af mange applikationsservere, eller mere – faktisk er scopet af java:global produktspecifikt.

Entries i ovenstående namespaces kan som sædvanligt registreres vha annotationer (@Resource, @EJB, mv) eller det respektive moduls deployment descriptor, eksempelvis web.xml eller ejb-jar.xml. Men endnu en markant nyhed i Java EE 6 platformen er det nu også blevet muligt at registrere entries i selve applikationens deployment descriptor, application.xml! Følgende eksempel viser en metode der anvender JNDI API’et til at få fat i en applikations scopet DataSource:

public DataSource getMyDataSource() throws NamingException {
    Context ctx = new InitialContext();
    return (DataSource) ctx.lookup(”java:app/env/jdbc/MyDataSource”)
}

Ovenstående funktionalitet kan man, som i Java EE 5, naturligvis også gøre en smule mere elegant ved hjælp af @Resource annotationen! I tillæg til de nye namespaces har annotationerne @Resource og @EJB også fået en ny attribut: lookup. Argumenter til denne attribut kan antage samme værdier som strenge til javax.naming.Context.lookup() metoden. Følgende eksempel demonstrerer en EJB, BusinessServiceImpl, der anvender dependency injection af en DataSource med applikations scope:

@Stateless
public class BusinessServiceImpl implements BusinessService{
    @Resource(lookup=”java:app/env/jdbc/MyDataSource”)
    private DataSource ds;
} 

Bemærk at der i vanlig tråd med Java EE platformens konfigurationsstruktur, også er tilført et tilsvarende <lookup-name> element som kan anvendes i de respektive modulers deployment descriptorer til at supplere eller overskrive annotationskonfigurationen.

Udover de namespace entries, som applikationerne selv registrerer (DataSources, JMS- ConnectionFactories og destinationer, osv), registreres som noget nyt også følgende:

  • Alle EJB’ere bliver registreret i hvert af de tre nye namespaces.
  • Indeværende moduls navn under java:module/ModuleName. Et moduls navn kan valgfrit angives i modulets respektive deployment descriptor (eksempelvis ejb-jar.xml og web.xml). Hvis det ikke er angivet anvendes modulets filnavn uden ”.jar/.war”.
  • Indeværende applikations navn under java:app/AppName. En applikations navn kan valgfrit angives i EAR filens deployment descriptor, application.xml. Hvis det ikke er angivet anvendes filnavnet uden ”.ear”.

Følgende eksempel viser en EJB, BusinessServiceImpl, der anvender dependency injection af en streng som angiver EJB-JAR modulets navn:

@Stateless
public class BusinessServiceImpl implements BusinessService{
    @Resource(lookup=”java:module/ModuleName”)
    private String appName;
} 
….EJB-JAR modulets deployment descriptor (ejb-jar.xml):
<ejb-jar …>
    <module-name>My EJB JAR module</module-name>
</ejb-jar>

Som en sidste lille finesse er muligheden for type angivelse i konfigurations variable (simple environment entries) blevet udvidet. Tidligere kunne man anvende følgende typer: String, Character, Byte, Short, Integer, Long, Boolean, Double, og Float. Med til nyhederne hører, at de nu også kan være af typerne: Class og vilkårlige subklasser af Enum. Følgende eksempel viser en servlet, der anvender dependency injection af en konfigurations variabel med component scope. Her injectes en enum constant.

public class MyServlet implements HttpServlet {
    @Resource(lookup=”java:comp/env/MyTimeUnit”)
    private TimeUnit unit;
}

….Web modulets deployment descriptor (web.xml):
<web-app …>
    <env-entry> 
        <env-entry-name>MyTimeUnit</env-entry-name>
        <env-entry-type>java.util.concurrent.TimeUnit</env-entry-type>
        <env-entry-value>MILLISECONDS </env-entry-value>
     </env-entry>
</web-app>

Det var en hel del nyheder i forbindelse med applikationskomponenternes naming environment! Der er vist ingen tvivl om at den helt store nyhed her er introduktionen af de nye namespaces – især java:global namespacet. Med sidstnævnte namespace har Java EE platformen omsider inkorporeret en standardog dermed portabel måde at referere globale JNDI resurser som EJB’ere og DataSources på!

DataSource definitioner

Med denne feature kan man lave en Java EE 6 applikation som bundler sin egen DataSource. Den bagvedliggende ide er faktisk ikke så ny endda: eksempelvis har IBM’s WebSphere Application Server igennem flere generationer understøttet samme funktionalitet i de såkaldte enhanced EAR files. Men med Java EE 6 kan vi nu gøre dette på en standardiseret og portabel måde på tværs af alle server produkter.

DataSources kan defineres, så de er tilgængelige i hver af de fire JNDI scopes:

  • java:comp – DataSources placeret her kan kun anvendes af en enkelt komponent
  • java:module – DataSources placeret her kan anvendes af alle komponenter i et modul
  • java:app – DataSources placeret her kan anvendes af alle komponenter i alle moduler i en applikation
  • java:global – DataSources placeret her kan anvendes af alle komponenter i alle applikationer i applikationsserveren

Som med alle andre namespace resurser, kan man definere DataSources vha. annotationer såvel som i deployment descriptorer. Hvis man anvender annotationer til at definere DataSources, bruges @DataSourceDefinition – som kan anvendes på en hvilken som helst container managed class (EJB, Servlet, filtre, listeners, interceptors mv.). Herunder ses en no-interface view EJB, der anvender @DataSourceDefinition til at erklære en DataSource på server niveau:

@DataSourceDefinition(name="java:global/MyApp/MyDataSource",
      className="com.foobar.MyDataSource",
      portNumber=6689,
      serverName="myserver.com",
      user="lance",
      password="secret"
   )
@Stateless
public class DataSourceBean {
}

Denne DataSource kan anvendes på helt normal vis i éns applikation – eller rettere: i enhver applikation på Java EE serveren! Herunder ses en no-interface view EJB, der anvender dependency injection vha @Resource annotationen for at kunne tilgå ovenstående DataSource:

@Stateless
public class UserDaoBean {
    @Resource(lookup=” java:global/MyApp/MyDataSource”)
    private DataSource ds;
}

Som alternativ til @DataSourceDefinition annotationen kan man også anvende <data-source> elementet i en deployment descriptor – det kan erklæres i ejb-jar.xml, web.xml, application-client.xml og ikke mindst application.xml. Herunder ses en ejb-jar.xml deployment descriptor, der erklærer en DataSource på server niveau – det resulterer i samme DataSource definition som ovenstående eksempel:

<ejb-jar ...>
    <data-source>
        <name>java:global/MyApp/MyDataSource</name>
        <class-name>com.foo.MyDataSoure</class-name>
        <server-name>myserver.com</server-name>
        <port-number>6689</port-number>
        <user>lance</user>
        <password>secret</password>
    </data-source>
</ejb-jar>

– Hvis man kombinerer de to muligheder så er det deployment descriptoren der får det sidste ord. Det er nemlig sådan, som med alle andre annotationer/XML konfiguration i Java EE platformen, at deployment descriptor indstillinger altid overskriver annotationer.

En typisk anvendelse af den nye DataSource funktionalitet kunne være:

  • Under udviklingen af Java EE 6 applikationer har man muligheden for at komme hurtigt udover stepperne ved at anvende annotationer til at angive DataSources. I denne process hardkoder man hostnavne/ipaddresser, porte, brugernavne, passwords mv.
  • Under deployment til en aktuel produktions server kan man så overskrive de hardkodede konfigurationer ved at anvende <data-source> i relevante deployment descriptor.

Selve erklæringen af DataSources er ret kraftfuld, idet man kan angive avancerede indstillinger som min/max connection pool size, max idle timeout på connections, max antal prepared statements, isolations niveau, leverandør specifikke properties mv.

Om DataSources nu fremover vil blive bundlet med Java EE 6 applikationerne er ikke nemt at svare på! Som med så mange andre overvejelser er der både fordele og ulemper ved muligheden. En væsentlig fordel er at distributionen af applikation og DataSource opsætning følges ad. En af konsekvenserne ved anvendelsen af Java EE 6 DataSource funktionaliteten er at den basalt set vil kræve at udviklingsorganisationer vælger een af følgende processer:

  • Der udvikles miljø-specifikke binære distributioner af applikationen (EAR fil, eksempelvis). For hver distribution anvendes en miljø-specifik deployment descriptor til konfigurere DataSourcen.
  • Man laver en en enkelt binær distribution og lader deployeren overskrive DataSource konfigurationen hver gang applikationen deployes.

Om disse processer er acceptable er op til den individuelle udviklingsorganisation. Typisk foretrækker større udviklingsorganisationer at miljøspecifikke elementer, som DataSources, konfigureres uafhængigt af applikationer: Når applikationer deployes i et specifikt miljø så refererer de bare til de allerede-opsatte resurser. Anvender man denne strategi, som jo altså er den eneste mulighed vi har i Java EE 5, undgår man at vælge een af ovenstående løsninger og har endvidere mulighed for at foretage miljøspecifik tuning som ikke bliver overskrevet hver gang applikationen opdateres.

Konklusion

Der er ingen tvivl om at Java EE 6 indeholder en række længe ventede og spændende opdateringer. Selvom nyhedsfokus traditionelt set har været på platformens underteknologier, som Servlets og EJBere, så har denne artikel vist at den også kommer med en række tværgående opdateringer – både funktionelt og proces mæssigt.

Eksempler på tværgående funktionelle opdateringer er at platformen nu baseres på Java SE 6, indeholder en masse opdaterede og nye APIs, kommer med 3 nye JNDI namespaces (java:moduel, java:app og java:global) og giver mulighed for at definere DataSources. Eksempler på tværgående procesmæssige nyheder er at platformen nu har defineret klare class loader regler som kan hjælpe udviklere med at skrive portable applikationer, introduceret pruning processen som i fremtiden skal luge ud i ikke-anvendte teknologier og sidst, men ikke mindst, defineret muligheden for Java EE profiler – specialiserede udgaver af platformen.

Hvis du har lyst til at grave dybere ned i platformen, så opfordres du til at læse videre i specifikationen (se links herunder). Med en god kop Java kan specifikationen faktisk læses af almindelige arkitekter og udviklere  – god fornøjelse!

Links

Her kan du kan downloade Java EE specifikationen som PDF:
[JSR316-Main] – JSR-000316 Java Platform, Enterprise Edition 6 (Final Release), javaee-6.0-fr

Her kan du kan downloade Java EE Web Profile specifikationen som PDF:
[JSR316-Spec] – JSR-000316 Java Platform, Enterprise Edition 6 Web Profile Specification (Final Release), javaee_web_profile-6.0-fr