Tomcat - Sdílený back-end
Téměř všechny příklady a tutoriály, jak konfigurovat Tomcat popisují jen ty nejjednodušší případy a aplikace. My jsme potřebovali Tomcat nakonfigurovat tak, aby několik web aplikací mohlo sdílet jediný modul obsahující servisní a DAO vrstvy. V tomto článku vám ukážu, jak na to.
Struktura naší aplikace
Deployment diagram
Front-end je tvořen několika webovými aplikacemi. V našem případě jsme měli pro každý výstupní formát speciální web aplikaci (WML, HTML). Tyto aplikace sdílí společný back-end, který obsahuje Spring application context a v něm nakonfigurovanou servisní a DAO vrstvu. Service locator pouze zabaluje Spring application context a webové aplikace si jej mohou najít v JNDI.
Proč je výhodou mít jediný společný back-end? V našem případě back-end obsahuje většinu business logiky, která je všem web aplikacím společná. Jedná se například o persistenci, cache, scheduler, logování statistik, atd. Další výhodou je, že můžete modifikovat web aplikaci bez nutnosti restartování back-endu, což se při vývoji hodí, protože back-end může startovat dost dlouho (v jednom z našich projektů back-end startoval půl minuty).
Testovací aplikace
Připravil jsem archív obsahující testovací aplikaci, skládající se z front-endu, back-endu a konfigurace tomcatu. Stáhněte si tomcat-example.zip a rozbalte někam na disk. Abyste mohli tuto aplikaci zkompilovat a spustit, musíte mít následující:
- JDK 1.5 a výše – http://java.sun.com/…ds/index.jsp
- Tomcat 6 – Stahněte si Tomcat z http://tomcat.apache.org/download-60.cgi. Pro naše účely není třeba instalovat, stačí někam rozbalit. Je užitečné nastavit si systémovou proměnnou TOMCAT_HOME na adresář, kde Tomcat máte.
- Apache Ant – http://ant.apache.org/bindownload.cgi
Po rozbalení archívu tomcat-example.zip byste měli mít na disku tuto strukturu:
───tomcat-example │ build.xml │ ├───core │ │ .classpath │ │ .project │ │ │ └───src │ └───itplace │ └───example │ └───core │ HelloService.java │ HelloServiceImpl.java │ ServiceLocator.java │ ServiceLocatorFactory.java │ ServiceLocatorImpl.java │ ├───tomcat │ │ run.cmd │ │ │ └───conf │ catalina.policy │ catalina.properties │ context.xml │ logging.properties │ server.xml │ tomcat-users.xml │ web.xml │ └───webapp1 │ .classpath │ .project │ ├───src │ └───itplace │ └───example │ └───webapp1 │ HelloServlet.java │ └───webapp └───WEB-INF │ web.xml │ └───classes
- tomcat-example/core obsahuje třídy back-endu
- tomcat-example/webapp1 je projekt obsahující web aplikaci.
- tomcat-exmple/tomcat obsahuje konfiguraci Tomcatu a dávku run.cmd, která nastartuje nakonfigurovaný tomcat.
Spuštěním příkazu ant v adresáři tomcat-example dojde ke zkompilování obou projektů core a webapp1. Výsledek kompilace se uloží do tomcat-example/core/bin resp. tomcat-example/webapp1/webapp/WEB-INF/classes.
Projekty core a webapp1 si můžete naimportovat do Eclipse, budete ale potřebovat říct Eclipse, kde má hledat knihovny serveru Tomcat.
Konfigurace Tomcatu
Nejprve prozkoumáme adresář tomcat-example/tomcat. Tento adresář neobsahuje instalaci Tomcatu ale pouze jeho konfiguraci. Pro spuštění naší aplikace je potřeba:
Nakonfigurovat classpath společnou všem aplikacím (common loader)
Podívejte se do souboru tomcat-example/tomcat/conf/catalina.properties. Na konci řádku 47 najdete toto:
common.loader= ...... ${catalina.base}/../core/bin
Proměnná ${catalina.base} je nastavená do adresáře tomcat-example/tomcat. Tomcat tedy do classpath společné všem web aplikacím i serveru samotného přidá třídy našeho back-endu.
Nakonfigurovat ServiceLocator
Třídu ServiceLocatorImpl
mužete najít v projektu
tomcat-example/core:
package itplace.example.core; public class ServiceLocatorImpl implements ServiceLocator { public HelloService getHelloService() { return new HelloServiceImpl(); } }
Vidíte, že tato implementace pouze vytváří novou instanci service HelloServiceImpl. Na tomto místě v reálném projektu může být použit například Spring a jeho BeanFactory.
Jak tedy přinutit Tomcat, aby při startu vytvořil jedinou instanci třídy ServiceLocatorImpl? Podívejte se do souboru tomcat-example/tomcat/conf/server.xml. Na řádku 40 najdete tento kousek xml:
<Resource name="serviceLocator" auth="Container" type="itplace.example.core.ServiceLocator" description="" factory="itplace.example.core.ServiceLocatorFactory" />
Pomocí tagu Resource deklarujeme JNDI resource typu
itplace.example.core.ServiceLocator
a jména
serviceLocator
. Tomcat pro jeho vytvoření použije továrnu
itplace.example.core.ServiceLocatorFactory
, která
vypadá takto:
package itplace.example.core; import java.util.Hashtable; import javax.naming.Context; import javax.naming.Name; import javax.naming.spi.ObjectFactory; public class ServiceLocatorFactory implements ObjectFactory { @Override public Object getObjectInstance(Object obj, Name name, Context nameCtx, Hashtable<?, ?> environment) throws Exception { System.out.println("creating new service locator"); return new ServiceLocatorImpl(); } }
Vidíte, že tovární metoda getObjectInstance
jednoduše
vytváří novou instanci třídy ServiceLocatorImpl
.
Zpřístupnit ServiceLocator webovým aplikacím
Tomcat již tedy inicializuje náš service locator při startu. Nyní je potřeba říct, jak k němu webové aplikace mohou přistupovat. Tuto konfiguraci najdete v souboru tomcat-example/tomcat/conf/context.xml na řádku 36:
<ResourceLink name="serviceLocator" global="serviceLocator" type="itplace.example.core.ServiceLocator" />
Tento kousek xml, již jen propojuje globální kontext serveru s kontextem webových aplikací. Nyní mohou web aplikace získat referenci na náš ServiceLocator standardním vyhledáním v JNDI. Podívejte se, jak toto vyhledání funguje v servletu HelloServlet, který najdete v projektu tomcat-example/webapp1:
.... Context initialContext; try { initialContext = new InitialContext(); ServiceLocator serviceLocator = (ServiceLocator) initialContext.lookup("java:comp/env/serviceLocator"); PrintWriter out = response.getWriter(); String message = serviceLocator.getHelloService().getHelloMessage("ITPlace"); out.println("HelloServlet: " + message); } catch (NamingException e) { throw new ServletException(e); } ....
Referenci na náš service locator získáme vyhledáním
java:comp/env/serviceLocator
v JNDI. Tuto část je pak dobré
přesunout do některé statické metody, aby jste nemuseli tento kód opakovat
v každém servletu.
Spuštění naší aplikace
To je celá věda, nyní můžete aplikaci spustit:
- nejprve vše zkompilujte – v adresáři tomcat-example spusťte příkaz
ant
. - v adresáři tomcat-example/tomcat spusťte dávku
run.cmd
. - otevřete svůj internetový prohlížeč a jděte na: http://localhost/…HelloServlet
Pokud vše proběhlo správně, měli byste vidět hlášku:
HelloServlet: HelloServiceImpl says: hello ITPlace !!!
.
Závěr
Ikdyž je Tomcat pouze servlet container, dají se s ním dělat psí kusy. Je ale na pováženou jestli není lepší pro běh aplikací podobných naší testovací použít některý z aplikačních serverů. Pokud vaše aplikace nepotřebuje vlastnosti a funkcionality aplikačního serveru a vystačí si se Springem (jako to bylo v našem případě), myslím, že je Tomcat díky své jednoduchosti dobrá volba.
Odkazy
- http://blog.itplace.cz/…-example.zip – testovací aplikace ke stažení.
- http://tomcat.apache.org/ – Apache Tomcat
- http://ant.apache.org/ – Apache Ant
- http://java.sun.com/javase/ – Java