Dovidenia, web.xml, v servletoch 3.0!

Ono sa to nezdá, ale servletová špecifikácia vo verzii 3.0 je s nami už dva a pol roka. Zoznam výhod si nájdete inde, ale teraz by som poukázal na radostnú fíčuru: v mnohých situáciách sa viete zbaviť XML. Dovi, web.xml a šialený deployment!

Konečne si môžete vyskúšať jednoduchú aplikáciu typu „Ahoj svet”, v ktorej vám postačia dve triedy.

Poďme na to.

Drobná poznámka

Ak nemáte radi Maven, asi je lepšie prestať čítať. Alebo to skúste a potom sa vytrápte s riešením závislostí a ručným balením WARiek, prípadne deployom do Tomcatu.

Založenie projektu

Založme nový mavenovský projekt:

C:\Projects> mvn archetype:generate

Z trilióna archetypov stačí potvrdiť výber Enterom, prípadne naklepkať:

org.apache.maven.archetypes:maven-archetype-quickstart

V ďalšom kroku sa Maven spýta na verziu, opäť Enterujeme. (V mojom Mavene je posledná verzia 1.1)

Vyplníme si postupne groupId (viď ukážka), artifactId (opäť viď ukážka), odenterujeme default verziu, opäť odenterujeme package a uvedieme Y, lebo všetko je ako má byť.

Define value for property 'groupId': : sk.upjs.ics.novotnyr
Define value for property 'artifactId': : servlet3
Define value for property 'version':  1.0-SNAPSHOT: :
Define value for property 'package':  sk.upjs.ics.novotnyr: :

Maven vykotí adresár C:\Projects\servlet3.

cd servlet3

Úprava pom.xml

Implicitný popisovač pom.xml v Mavene je v tomto prípade príliš biedny, aby sa dal použiť. Predovšetkým potrebujeme zmeniť typ výsledného balíčka: štandardom je jar, ale naša webová monšteraplikácia potrebuje mať typ war:

Chopme sa rozumného editora:

notepad pom.xml

a upravme riadok <packaging> na

<packaging>war</packaging>  

Keby váš už teraz trhalo vyrábať WAR, Maven bude nervózny:

mvn package

[ERROR] Failed to execute goal org.apache.maven.plugins:maven-war-plugin:2.1.1:war (default-war) on project servlet3: Error assembling WAR: webxml attribute is required (or pre-existing WEB-INF/web.xml if executing in update mode) -> [Help 1]

Po slovensky to znamená, že balíčkovaciemu plug-inu chýba ku šťastiu web.xml. Hoj, kedysi by ani vo sne nenapadlo vývojárom, že raz nadíde doba, keď web.xml nebude povinnou súčasťou webovej aplikácie.

Napraviť to môžeme ďalšou úpravou pom.xml. V koreňovom elemente <project> načim doklepať podlement <build> a v ňom nakonfigurovať plug-in (zásuvný modul, povedal by Ľudevít Š.)

Balíčkovanie WARov má na starosti plug-in maven-war. Používam ho v poslednej verzii (2.2), možno časom vyjde novšia. Najdôležitejšia je stať failOnMissingWebXml, kde treba plug-inu naznačiť, že v našom projekte sa web.xml fakt nedočká:

<build>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-war-plugin</artifactId>
            <version>2.2</version>
            <configuration>
                <failOnMissingWebXml>false</failOnMissingWebXml>
            </configuration>
        </plugin>
    </plugins>
</build>

Teraz už môžeme radostne releasnúť náš prvý WAR, aj keď nebude dávať zmysel:

mvn package

V target sa zjaví c:\Projects\servlet3\target\servlet3-1.0-SNAPSHOT.war, ale ani sa nepokúšajte ho pchať do Tomcatu, či iného servletového kontajnera, lebo nie je tam nič na spúšťanie.

Doplňme servlety!

Ak chceme vyvíjať servlety, potrebujeme získať JAR archív s interfaceami špecifikácie Servlet 3.0. Ako je všeobecne známe, servlet je klasická trieda, ktorá dedí od abstraktnej triedy javax.servlet.http.HttpServlet. A práve táto trieda sa nachádza v príslušnom archíve.

Dodajme závislosť

Vďaka Mavenu stačí dodať jednu závislosť a je to.

V pom.xml, do bloku <dependencies> (mal by tam byť spomenutý JUnit), dodajme:

<dependency>
    <groupId>javax.servlet</groupId>
    <artifactId>javax.servlet-api</artifactId>
    <version>3.0.1</version>
    <scope>provided</scope>
</dependency>

Prečo je tam verzia 3.0.1? Nik nevie: to je jedna z mnohých záhad centrálneho úložiska Mavenu.

Špeciálne nezabudnime na špeciálny scope. V tomto prípade používame provided, čo znamená, že oproti tejto závislosti sa bude kompilovať náš projekt, ale v čase behu bude závislosť splnená (providenutá) servletovým kontajnerom a netreba ju pchať do výsledného WARka. Ak zabudnete na tento scope, žiadna veľká katastrofa sa neudeje, akurát Tomcat vás obveselí kopou varovných hlášok o prítomnosti zakázaných knižníc v CLASSPATH.

Doplňme servlet!

Vytvorme jednoduchý servlet v balíčku sk.upjs.ics.novotnyr, čo podľa konvencií Mavenu zodpovedá adresáru src/main/java/sk/upjs/ics/novotnyr:

notepad src/main/java/sk/upjs/ics/novotnyr/HelloServlet

A obsahom jest:

package sk.upjs.ics.novotnyr;
 
import java.io.IOException;
import java.io.PrintWriter;
 
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
 
@WebServlet("/")
public class HelloServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        PrintWriter out = resp.getWriter();
        out.println("Hello world!");
    }
}

Všimnime si krásnu anotáciu @WebServlet nad triedou. Tá označí servlet ako… servlet, a zároveň mu nastaví automatické mapovanie na URL adresu /.

Za čias web.xml by sme museli uvádzať dvojkombo elementov:

<servlet>
    <servlet-name>HelloServlet</servlet-name>
    <servlet-class>sk.upjs.ics.novotnyr.HelloServlet</servlet-class>
</servlet>

<servlet-mapping>
    <servlet-name>HelloServlet</servlet-name>
    <url-pattern>/</url-pattern>
</servlet-mapping>

ale našťastie to už nie je potrebné.

Servlet je týmto hotový (a to vrátane konfigurácie). Nič viac netreba.

Nasadenie!

Máte minimálne dve možnosti:

  1. vybudovať WAR, ten zdrapnúť a nasadiť napr. do Tomcatu
  2. spustiť projekt pomocou plug-inu pre kontajner Jetty.

WAR do Tomcatu

WAR vybudujete už spomínaním spôsobom. Výsledkom nasledovného príkazu bude WARko v adresári target.

mvn package

Ak máte Tomcat, spustite ho, a prekopírujte WAR do tomcatieho adresára webapps, mala by prebehnúť automatická inicializácia aplikácie. Navštíviť ju môžete na:

http://localhost:8080/servlet3-1.0-SNAPSHOT/

Tešte sa z Hello World!

Autospustenie s plug-inom

Alternatívne využite fintivý plug-in, ktorý spustí vašu webovú aplikáciu v minikontajneri Jetty. Výhodou je, že nemusíte vôbec nič ťahať, inštalovať, ani spúšťať: všetko za vás spraví Maven.

Otvorte zase pom.xml (ak ste ho omylom medzičasom zavreli) a do elementu <build> a podelementu <plugins>, niekde pod konfiguráciu maven-war stačí vložiť konfiguráciu plug-inu (zásuvného modulu, vraví Ľudevít) maven-jetty:

<plugin>
    <groupId>org.mortbay.jetty</groupId>
    <artifactId>jetty-maven-plugin</artifactId>
    <version>8.1.4.v20120524</version>
</plugin>

Čas spustiť Jetty!

mvn jetty:run

Chrúst, chrúst a Jetty beží na porte 8080. Poobdivovať vašu webaplikáciu môžete na známej adrese:

http://localhost:8080/servlet3-1.0-SNAPSHOT/

Keďže váš servlet sedí na koreňovom adresári, zjaví sa vytúžený Hello World.

Šialený sufix

Ak sa vám nepáči šialený sufix servlet3-1.0-SNAPSHOT a chceli by ste napr. normálnejší:

http://localhost:8080/servlet3

stačí dodať element <finalName> do pom.xml pod element <build>:

<build>
    <finalName>imd</finalName>
    ...

Sumár

Nebyť zverín s Mavenom, ktoré nám v konečnom dôsledku uľahčili život, je to veľmi ľahké a nasadiť triviálnu servletovú aplikáciu dokážeme lusknutím prsta.

Najdôležitejšie je, že web.xml je nepotrebný: stačí inteligentne ošperkovať triedu servletu anotáciou @WebServlet, zabaliť to do WARka a môžete deployovať.

Prílohy

Môže sa hodiť fungujúci projekt, vrátane pom.xml, to keby ste sa stratili v copy-pastovaní:

servlet3

3 thoughts on “Dovidenia, web.xml, v servletoch 3.0!

  1. …veľmi pekné, nenašiel by sa odkaz na to, ako sa zbaviť ďalších vecí z web.xml, napr. filtrov, context-parametrov atď?

  2. Ostatné anotácie možno nájsť v dokumentácii k javax.servlet.annotation [1]. Letmo:

    • @WebFilter: pre filtre
    • @WebListener: pre ServletContextListener, ServletContextAttributeListener, ServletRequestListener, ServletRequestAttributeListener, HttpSessionListener, či HttpSessionAttributeListener
    • @WebInitParam: pre inicializačný parameter v <init-param>

    [1] http://docs.oracle.com/javaee/6/api/javax/servlet/annotation/package-summary.html

  3. este pomocka ako nastavit iny port + context path bez nutnosti menit final name:

      <plugin>
        <groupId>org.mortbay.jetty</groupId>
        <artifactId>jetty-maven-plugin</artifactId>
        <version>8.1.5.v20120716</version>
        <configuration>
          <webApp>
            <contextPath>/simple</contextPath>
          </webApp>
          <connectors>
            <connector implementation="org.eclipse.jetty.server.nio.SelectChannelConnector">
              <port>9090</port>
              <maxIdleTime>60000</maxIdleTime>
            </connector>
          </connectors>
        </configuration>
      </plugin>
    

Pridaj komentár

Vaša e-mailová adresa nebude zverejnená. Vyžadované polia sú označené *