суббота, 12 июля 2008 г.

Совместное использование Tapestry и Spring


Давно задумывал написать что-то полезное для блоггеров и вконце-концов родилась идея конечно же социальной сети. Да, да, можете ругать за очередной велосипед, но как говорится у своего велосипеда колеса круглее. Собственно вопрос на чем реализовывать особо не стоял, т.к. решено было реализовывать на Java, заодно и получить опыт проектирования с нуля пусть не очень сложного, но все же J2EE приложения. Единственная проблема, которую я сейчас вижу это проблема последующего развертывания - нужно будет выбрать java-хостинг (скорее всего буржуйский) и как-то залить туда приложение. Впрочем проблему деплоя на виртуальный хостинг я еще опишу.

Впрочем выбор Java в качестве платформы для реализации приложения ставит перед нами еще одну проблему выбора - проблему выбора библиотек и фреймворков. Так как я имею опыт работы с Tapestry (не сильно большой, но все же) и этот опыт положительный, для реализации веб-части я выбрал именно данный фреймворк. Tapestry основан на IoC-контейнере Hivemind, но я отказался от его использования в пользу более мощного Spring. Почему Spring, а не например Guice? Потому что Spring позволяет не изобретать велосипед - определение источников данных, подключение Hibernate, AOP, управление транзакциями - это все есть в Spring (точно так же как и возможность определения Generic DAO, интерцепторов и многих других вкусностей). Собственно разобраться со Spring это тоже одна из целей моего проекта.

Так же не маловажную роль сыграл тот факт, что Spring поддерживается Tapestry "из коробки". А вот о том, как подключить Spring к Tapestry и инъектить эти бины на страницы и в компоненты, мы и поговорим.


Для этого необходимо написать фабрику, которая построит контекст Spring'овского веб-приложения. Код данной фабрики может быть следующим:

public class SpringContextFactory {

   

    private ServletContext servletContext;

    private WebApplicationContext appContext;

   

    public WebApplicationContext getAppContext() {

        return appContext;

    }    

   

    public ServletContext getServletContext() {

        return servletContext;

    }



    public void setServletContext(ServletContext servletContext) {

        this.servletContext = servletContext;

        appContext = WebApplicationContextUtils.getWebApplicationContext(getServletContext());

    }

}

 


Теперь необходимо указать HiveMind'у что данную фабрику можно использовать в качестве SpringContextFactory. Делается это в файле-конфиге HiveMind - /META-INF/hivemodule.xml.

<module id="vposte" version="1.0.0" package="ru.vposte">

 

    <contribution configuration-id="hivemind.ApplicationDefaults">

        <default symbol="hivemind.lib.spring-bean-factory" value="service-property:vposte.SpringContextFactory:appContext"/>

    </contribution>

 

    <service-point id="SpringContextFactory">        

        Create WebApplicatonContext for Spring

        <invoke-factory>

            <construct class="SpringContextFactory">

                <set-service property="servletContext" service-id="tapestry.globals.ServletContext"/>

            </construct>

        </invoke-factory>

    </service-point>

   

</module>


Здесь vposte. - идентификатор приложения. В случае вашего приложения он может быть изменен.

Ну и конечно же, чтобы Spring работал необходимо прописать Spring'овский ServletContextLoaderListener в web.xml, добавив туда такие строчки:

<servlet-mapping>

   <servlet-name>vposte</servlet-name>

   <url-pattern>/app</url-pattern>

</servlet-mapping>

       

<context-param>

   <param-name>contextConfigLocation</param-name>

   <param-value>/WEB-INF/spring-context/applicationContext.xml</param-value>

</context-param>

   

<listener>

    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>

</listener>


Теперь Spring будет замечательно работать с нашим Tapestry приложением (или наоборот, теперь Tapestry будет фронт-контроллером нашего Spring-приложения).

Для того, чтобы инъектировать Spring-бины на страницы Tapestry необходимо использовать аннотации вида:

@InjectObject("spring:registrService")

public abstract IUserRegistrationService getUserRegistrationService();



Здесь spring - обязательный префикс, который говорит HiveMind'у, что бин нужно грузить из контекста Spring. registrService - название бина, описанное в Spring-контексте (например xml-файлах описания бинов).

Собственно и все, данных шагов вполне достаточно, чтобы использовать всю мощь Spring для создания бизнес-части приложения и красоту и удобство Tapestry для разработки веб-уровня.

З.Ы. вопросы и коментарии как всегда приветствуются.


Системы контроля версий. Git. - замечательная статья об использовании Git для начинающих.

Spring Antipatterns - обсуждение антипаттернов использования Spring в ru_java

Понравилось сообщение - подпишись на блог

Комментариев нет:

Отправить комментарий

Любой Ваш комментарий важен для меня, однако, помните, что действует предмодерация. Давайте уважать друг друга!