Archív

Archív pro

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

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í:

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/webap­p1/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/con­f/catalina.pro­perties. 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/con­f/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/con­f/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

Jan Šmuk Nezařazené

VisualVM - vítězství v soutěži

15.08.2009

Náš článek VisualVM – tool for profiling Java applications zvítězil v soutěži Java VisualVM Blogging Contest.

Článek popisuje, jak jsem postupoval při odhalování slabých míst ve hře Java Dash. Neobsahuje ale řešení těchto problémů, což je velká škoda. Slibuji, až bude čas, ještě se k tomu vrátím :)

Ale i přesto byl tento článek vybrán jako jeden z nejlepších v poměrně silné konkurenci.

Odkazy

Jan Šmuk Java, Performance