Programmering

REST for Java-utviklere, del 2: Restlet for trette

Open Source Restlet API reduserer arbeidsmengden som er involvert i å bygge og konsumere RESTful APIer i Java. I denne andre artikkelen i REST for Java-utviklere -serien introduserer Brian Sletten deg for Restlet og går gjennom et eksempel på et program for å distribuere grensesnittene i servletcontainerne du bruker i dag, samtidig som han forbereder seg på fremtidens systemer. Brian introduserer også kort JSR 311: JAX-RS, Suns forsøk på å integrere RESTful APIer med Java EE-stakken.

Java-utviklere har lenge vært interessert i REST-arkitektoniske stilen, men få har ennå reist avstanden mellom den kjente verdenen av gjenstander og den RESTful verden av ressurser. Selv om vi kanskje liker det faktum at RESTful-tjenester kan produseres eller konsumeres av andre språk, hater vi å måtte konvertere data til og fra byte-strømmer. Vi hater å måtte tenke på HTTP når vi bruker verktøy som Apache HTTP Client. Vi ser lengselende på objekter skapt av wsdl2java kommando, som lar oss sende argumenter til en SOAP-tjeneste like enkelt som alle andre metoder, og feie detaljene for å påkalle en ekstern tjeneste under teppet. Og vi synes servletmodellen er litt for koblet fra ressursene som produseres. Det er nok å si det mens vi har vært i stand å bygge RESTful tjenester fra bunnen av, det har ikke vært en hyggelig opplevelse.

REST for Java-utviklere

Les serien:

  • Del 1: Det handler om informasjonen
  • Del 2: Restlet for trette
  • Del 3: NetKernel

Noen ganger har politiske spørsmål forverret de tekniske hindringene. Mange ledere føler at SOAP-baserte webtjenester er den foreskrevne måten å bygge serviceorienterte arkitekturer (SOAer) i Java EE. Dette endrer seg med fremveksten av viktige aktiviteter som JSR 311, JAX-RS: Java API for RESTful Web Services, som du vil lære om i denne artikkelen. Om ikke annet, legitimerer denne innsatsen RESTful utvikling i JEE-rommet.

I mellomtiden har hjelp kommet. På elegant måte gjør open source Restlet-rammeverket det enkelt å unngå de vanskelige problemene som kan oppstå ved bruk av tradisjonell JEE-teknologi for å bygge og konsumere RESTful-tjenester.

Restlets røtter

I et forsøk på å løse noen av de tekniske problemene som er involvert i å gjøre REST med Java, prøvde Jérome Louvel, en fransk programvarekonsulent, å skape et rammeverk som ville gi en mer naturlig passform. Han så først på NetKernel-miljøet som utgangspunkt. Så mye som han likte det, passet det ikke perfekt for det API-fokuserte rammeverket han søkte å gjøre tilgjengelig. Opplevelsen bidro til å påvirke hans tenkning om hva slags ting som et REST-orientert miljø kan tilby. (Den neste artikkelen i denne serien vil utforske NetKernel nærmere.)

Da Louvel arbeidet med rammeverket sitt, utviklet han tre mål:

  • Enkle handlinger skal være enkle for grunnleggende bruk. Standardinnstillingene skal fungere med minimal innsats, men også gi rom for mer komplekse konfigurasjoner.
  • Kode skrevet til dette API-et skal være bærbar på tvers av containere. Selv om servletbaserte systemer kan flyttes mellom containere som Tomcat, Jetty og IBM WebSphere, hadde Louvel et større bilde i tankene. Servlet-spesifikasjonen er knyttet til HTTP og en blokkerende I / O-modell. Han ønsket at API-en hans skulle kunne skilles fra begge disse og distribueres i containerne som er i bruk i dag. Han ønsket også at de skulle kunne brukes med liten innsats i alternative og nye containere som Grizzly, AsyncWeb og Simple Framework.
  • Det skal ikke bare berike serversiden ved å produsere RESTful-grensesnitt i Java, men også klientsiden. De HttpURLConnection klasse og Apache HTTP-klient er for lavt nivå til å integreres rent direkte i de fleste applikasjoner.

Med disse målene i tankene satte han seg for å produsere Restlet API. Etter noen år i flux ble API-et stabilt, og et samfunn vokste rundt det. I dag har kjernen API en livlig brukerbase, og betydelig aktivitet er i gang for å støtte integrasjon med andre verktøysett og tiltak som JAX-RS. (Louvel er nå med i JAX-RS-ekspertgruppen.)

Restlet grunnleggende

En grunnleggende server med Restlet API kan umulig være enklere, som vist i liste 1.

Oppføring 1. En grunnleggende server med Restlet

pakke net.bosatsu.restlet.basic; import org.restlet.Restlet; importere org.restlet.Server; importer org.restlet.data.MediaType; importer org.restlet.data.Protocol; importer org.restlet.data.Request; importer org.restlet.data.Response; offentlig klasse SimpleServer {public static void main (String [] args) kaster Unntak {Restlet restlet = new Restlet () {@Override public void handle (Request request, Response response) {response.setEntity ("Hello, Java RESTafarians!", MediaType.TEXT_PLAIN); }}; // Unngå konflikter med andre Java-containere som lytter på 8080! ny server (Protocol.HTTP, 8182, restlet) .start (); }}

Denne applikasjonen gjør ikke mye (bortsett fra å spre god stemning), men den viser frem to av Restlets grunnleggende prinsipper. For det første er enkle ting enkle. Mer komplekse aktiviteter er absolutt mulig, men du bekymrer deg bare for dem når du trenger det. REST mangler ikke muligheten til å håndheve sikkerhet, begrensninger, innholdsforhandlinger eller andre viktige oppgaver. Disse forblir stort sett ortogonale aktiviteter, ganske forskjellige fra prosessen med å tilfredsstille en RESTful API. Du legger kompleksiteten på etter behov.

For det andre er koden i liste 1 designet for å være bærbar blant containertyper. Legg merke til at den ikke spesifiserer en container. Restlets er de faktiske ressursene som til slutt svarer på forespørslene. Det skilles ikke mellom containeren som håndterer forespørselen og informasjonssvaret, slik det kan være i servletmodellen. Hvis du skriver inn koden i en IDE og legger til avhengigheter på org.restlet.jar og com.noelios.restlet.jar arkiver, kan du kjøre applikasjonen og skulle se en loggmelding som denne:

7. desember 2008 23:37:32 com.noelios.restlet.http.StreamServerHelper start INFO: Starte den interne HTTP-serveren

Pek en nettleser mot // lokal vert: 8182, og du bør se den vennlige hilsenen.

Bak kulissene, den org.restlet.jar inneholder alle de viktigste grensesnittene for denne API-en. De com.noelios.restlet.jar inneholder en grunnleggende implementering av disse grensesnittene og gir en standard HTTP-håndteringsfunksjon. Du vil ikke ønske å gå i produksjon med denne HTTP-motoren, men det er veldig praktisk for utviklings- og testformål. Du trenger ikke starte en større container for å teste din RESTful-kode. Enhets- og integrasjonstesting kan bli mye lettere som et resultat.

Prøven i oppføring 1 bruker mye standardadferd for å opprette en standard applikasjon eksempel (jeg skal diskutere applikasjon i neste eksempel) og lytt etter HTTP-protokollforespørsler på port 8182. The StreamServerHelper klassen begynner å lytte på denne porten og sender forespørsler til Restlet eksempel når de kommer inn.

Louvels mål om å støtte RESTful Java på klientsiden blir også oppfylt, som du kan se i Listing 2.

Oppføring 2. En Restlet-klient

pakke nett.bosatsu.restlet.basic; importere java.io.IOException; import org.restlet.Client; importer org.restlet.data.Protocol; offentlig klasse SimpleClient {public static void main (String [] args) kaster IOException {String uri = (args.length> 0)? args [0]: "// localhost: 8182"; Klientklient = ny klient (Protocol.HTTP); client.get (uri) .getEntity (). skriv (System.out); }}

Med SimpleServer fortsatt kjører, skal lanseringen av denne nye klientkoden med de samme JAR-avhengighetene skrive ut den vennlige hilsenen til konsollen. Utskrift av utdata i denne stilen vil åpenbart ikke fungere for binærorienterte MIME-typer, men igjen er det et praktisk utgangspunkt.

Ikke-CRUD eksempel

De fleste pedagogiske REST-eksemplene viser CRUDish-tjenester (Opprett, Hent, Oppdater, Slett) rundt enkle objekter. Selv om denne stilen absolutt fungerer bra med REST, er det på ingen måte den eneste tilnærmingen som gir mening - og de fleste av oss er uansett lei av CRUD-eksempler. Følgende eksempel viser det grunnleggende i et Restlet-program ved å pakke stavekontrollen Jazzy med åpen kildekode.

REST handler om å administrere informasjon, ikke å påberope vilkårlig atferd, så du må være forsiktig når du vurderer et atferdsorientert API som Jazzy. Trikset er å behandle RESTful API som et informasjonsrom for ord som finnes og ikke finnes i ordbøkene i bruk. Problemet kan løses på en rekke måter, men denne artikkelen vil definere to informasjonsrom. /ordbok brukes til å administrere ord i ordboken. /stavekontroll brukes til å finne forslag til ord som ligner feilstavede ord. Begge fokuserer på informasjon ved å vurdere fravær eller tilstedeværelse av ord i informasjonsrommene.

I en RESTful-arkitektur kan denne HTTP-kommandoen returnere en definisjon av et ord i ordboken:

GET // localhost: 8182 / ordbok /ord

Det vil sannsynligvis returnere HTTP-responskoden "Ikke funnet" for ord som ikke er i ordboken. I dette informasjonsområdet er det greit å indikere at ord ikke eksisterer. Jazzy gir ikke definisjoner for ord, så jeg legger igjen innhold som en øvelse for leseren.

Denne neste HTTP-kommandoen skal legge til et ord i ordboken:

PUT // localhost: 8182 / ordbok /ord

Dette eksemplet bruker SETTE fordi du kan finne ut hva URI i /ordbok informasjonsområdet bør være på forhånd, og utstede flere SETTEs skal ikke utgjøre en forskjell. (SETTE er en idempotent forespørsel, som . Å utstede den samme kommandoen flere ganger burde ikke gjøre noen forskjell.) Hvis du vil legge til definisjoner, kan du sende dem inn som kropper til SETTE behandler. Hvis du vil godta flere definisjoner over tid, kan det være lurt POST disse definisjonene i, fordi SETTE er en overskrivingsoperasjon.

Ikke overse synkronisering

For å holde eksemplene fokusert, tar denne artikkelen ingen spesiell oppmerksomhet til synkroniseringsproblemer. Ikke behandle produksjonskoden din så nonchalant! Rådfør deg med en ressurs som Java samtidighet i praksis for mer informasjon.

De Restlet tilfeller som jeg oppretter, må være bundet til de aktuelle informasjonsrommene, som vist i liste 3.

Oppføring 3. En enkel RESTful stavekontroll

pakke net.bosatsu.restlet.spell; importer com.swabunga.spell.event.SpellChecker; importer com.swabunga.spell.engine.GenericSpellDictionary; importere com.swabunga.spell.engine.SpellDictionary; importere java.io.File; importere java.io.FileNotFoundException; importere java.io.IOException; importer org.restlet.data.Protocol; import org.restlet. *; public class SpellCheckingServer utvider applikasjonen {public static String dictionary = "Restlet / dict / english.0"; offentlig statisk SpellDictionary spellingDict; offentlig statisk stavekontroll stavekontroll; offentlig statisk Restlet spellCheckerRestlet; offentlig statisk Restlet-ordbokRestlet; statisk {prøv {spellingDict = ny GenericSpellDictionary (ny fil (ordbok)); stavekontroll = ny stavekontroll (stavingsdikt); spellCheckerRestlet = ny SpellCheckerRestlet (stavekontroll); dictionaryRestlet = ny DictionaryRestlet (stavekontroll); } fange (Unntak e) {e.printStackTrace (); }} offentlig statisk ugyldig hoved (String [] args) kaster Unntak {Komponentkomponent = ny Komponent (); component.getServers (). add (Protocol.HTTP, 8182); SpellCheckingServer spellingService = ny StaveCheckingServer (); component.getDefaultHost (). attach ("", spellingService); component.start (); } public Restlet createRoot () {Router router = new Router (getContext ()); router.attach ("/ stavekontroll / {word}", stavekontrollRestlet); router.attach ("/ ordbok / {ord}", ordbokRestlet); retur ruteren; }}

Etter at den har bygd opp ordbokforekomsten og stavekontrollen, er Restlet-oppsettet i Listing 3 litt mer komplisert enn i det tidligere grunnleggende eksemplet (men ikke mye!). De Stavekontrollserver er en forekomst av en Restlet applikasjon. An applikasjon er en organisasjonsklasse som koordinerer distribusjon av funksjonelt tilkoblede Restlet tilfeller. Omgivelsene Komponent spør en applikasjon for roten Restlet ved å ringe createRoot () metode. Roten Restlet returnert angir hvem som skal svare på eksterne forespørsler. I dette eksemplet heter en klasse Ruter brukes til å sende til underordnede informasjonsrom. I tillegg til å utføre denne kontekstbindingen, setter den opp et URL-mønster som gjør at "ord" -delen av URL-en kan være tilgjengelig som attributt på forespørselen. Dette vil bli utnyttet i Restlets opprettet i liste 4 og 5.

De DictionaryRestlet, vist i liste 4, er ansvarlig for å håndtere forespørsler om manipulering av /ordbok informasjonsrom.

$config[zx-auto] not found$config[zx-overlay] not found