- 04-08-2008
Веб Приложение на ОСГИ
Simple Web-application on OSGi.
Технология OSGi позволяет создавать модульные приложения, которое легко может конфигурироваться путем добавления,удаления или обновления модулей. В данном примеры мы рассмотрим создания простейшего веб-приложения как часть (модуль) другого приложения, основанного на OSGi.
В моем примере будут использоваться Tomcat 5.5, Spring MVC, Apache DBCP и в качестве реализации OSGi выбран Equanox, база данных PostgreSQL.
Для начала необходимо скачать дистрибутивы вышесказанных библиотек, но в в виде osgi-модулей или бандлов и сам equnox (http://www.eclipse.org/equinox/). Обычные дистрибутивы библиотек отличаются от osgi-модулей лишь тем что в сборке последних хранится файл manifest.mf в котором заданы какие пакеты классов необходимы для работы данного модуля и какие пакеты классов модуль экспортирует в приложение, то есть какие пакеты могут использовать другие модули в этом приложении. Кроме этой информации в файле манифеста есть еще много настроек, но пока они нам не нужны.
Вот весь список бандлов, используемых в моем примере:
catalina.osgi.jar
catalina.start.osgi.jar
com.springsource.junit.jar
com.springsource.net.sf.cglib.jar
com.springsource.org.aopalliance.jar
com.springsource.org.apache.commons.dbcp-1.2.2.osgi.jar com.springsource.org.apache.commons.pool-1.4.0.jar
com.springsource.org.objectweb.asm.jar
com.springsource.org.postgresql.jdbc3-8.3.603.jar
com.springsource.slf4j.api.jar
com.springsource.slf4j.log4j.jar
com.springsource.slf4j.org.apache.commons.logging.jar
commons-el.osgi.jar
easymock.jar
jasper.osgi.jar
jsp-api.osgi.jar
jstl.osgi.jar
log4j.configuration-1.1.0.jar
log4j.osgi.jar mx4j.osgi.jar
org.eclipse.osgi.jar
servlet-api.osgi.jar
spring-aop.jar
spring-beans.jar
spring-context.jar
spring-context-support.jar
spring-core.jar
spring-osgi-core.jar
spring-osgi-extender.jar
spring-osgi-io.jar
spring-osgi-test.jar
spring-osgi-web.jar
spring-osgi-web-extender.jar
spring-test.jar
spring-web.jar
spring-webmvc.jar
Самые основные это catalina.osgi.jar – содержит классы Tomcat, catalina.start.osgi.jar – используя классы из catalina.osgi.jar запускает Tomcat во время своей загрузки. То есть этот модуль содержит BundleActivator , который вызывается при старте бандла. Идем дальше, com.springsource.org.postgresql.jdbc3-8.3.603.jar – это драйвер базы данных PostgreSQL, com.springsource.org.apache.commons.dbcp-1.2.2.osgi.jar - Apache Connection Pool. Дальше стоит выделить бандл spring-osgi-web-extender.jar, он занимается тем что следит является ли бандл веб-приложением, тоесть war-ником, и если да и при условии что уже запущен веб-контейнер, в нашем случае Tomcat, то он разворачивает (деплоит) данное веб-приложение. Все остальные бандлы необходимы для работы вышеперечисленных.
Бандлы можно скачать либо в репозитории Spring: http://www.springsource.com/repository/app/ либо в репозиторях Maven: http://www.mavenreposearch.com/.
Итак, можно приступать к запуску. В папке где лежит equinox создаем папку configuration, в ней файл config.ini с примернол таким содержанием:
eclipse.ignoreApp=true
osgi.noShutdown=true
osgi.console=
osgi.clean=true
osgi.bundles=com.springsource.slf4j.api.jar@start ….
Особо не вдаваясь в первые 4 строчки, стоит обратить вримания на последнюю. Она содержит бандлы , которые добавляются в систему. Бандлы подключаются в формате путь(относительно той директории где лежит equanox)@start, если бандл не нужно активировать то указываем просто путь к дистрибутиву.
Запускаем Equanox :
java -jar libs4/org.eclipse.osgi.jar.
Дальше можно посмотреть статус всех бандлов с помощью команды ss. Если все хорошо то статус Active, если не найдены зависимости, то статус Installed, и если бандл неактивен то статус Resolved. Если при запуске бандла не реализована какая-либо зависимость, то в папке configuration создается лог-запись, по которой можно узнать в чем проблема.
Создаем свой первый бандл, который содержит лиш интерфейс.
Дальше можно посмотреть статус всех бандлов с помощью команды ss. Если все хорошо то статус Active, если не найдены зависимости, то статус Installed, и если бандл неактивен то статус Resolved. Если при запуске бандла не реализована какая-либо зависимость, то в папке configuration создается лог-запись, по которой можно узнать в чем проблема.
Создаем свой первый бандл, который содержит лиш интерфейс.
***
*/
package org.osminog.service;
*** @author Alexander Galibey
*
*/
public interface MessageService {
String getMessage();}
И соответсвенно файл манифеста:
Bundle-Version: 1.0
Bundle-SymbolicName: org.osminog.service
Bundle-Name: Service Interfaces
Bundle-Vendor: OSMinog group
Export-Package: org.osminog.service
Bundle-ManifestVersion: 1
Обратите внимание на строку,выделенную жирным шрифтом, она означает что пакет org.osminog.service другим модулям в системе.
Дальше создаем другой бандл, который будет использовать этот пакет.
***
*/
package org.osminog.service.impl;
import java.sql.Connection;import java.sql.ResultSet;
import java.sql.Statement;
import javax.sql.DataSource;
import org.osminog.service.MessageService;
*** @author Alexander Galibey
*
*/
public class MessageServiceImpl implements MessageService {
private DataSource dataSource;
public DataSource getDataSource() {return dataSource;
}
public void setDataSource(DataSource dataSource) {this.dataSource = dataSource;
}
public String getMessage() {
String message = null;
try{
Connection con = dataSource.getConnection();
Statement st = con.createStatement();
ResultSet rs = st.executeQuery("select hello world! as text");
if (rs.next()){message = rs.getString(1);
}
}catch (Exception e){e.printStackTrace();
}
return message;
}}
Манифест:
Bundle-Version: 1.0Bundle-SymbolicName: org.osminog.serviceImpl
Bundle-Name: Service Implementation
Bundle-Vendor: OSMinog group
Bundle-ManifestVersion: 2
Import-Package: org.osminog.service,javax.sql,org.postgresql;version="[8.3.603,8.3.603]",org.apache.commons.dbcp;version="[1.2.2.osgi,1.2.2.osgi]".
Этот модуль импортирует пакет с нашим интерфейсов, а также пакет драйвера базы данных и библиотеки Apache DBCP.
Также в этом модуле используется Spring Context. Для этого в папке META-INFSpring созданы два файла:
messageService.xml - обычный спринговый контекст:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean name="messageService" class="org.osminog.service.impl.MessageServiceImpl" ><property name="dataSource">
<ref bean="dataSource" />
</property>
</bean>
<bean id="dataSource"
class="org.osminog.service.impl.SimpleDataSource">
<property name="driverClassName">
<value>org.postgresql.Driver</value>
</property>
<property name="url">
<value>jdbc:postgresql:postgres</value>
</property>
<property name="username">
<value>postgres</value>
</property>
<property name="password">
<value>12345</value>
</property>
</bean>
</beans>
И messageService-osgi.xml для обьявления сервисов:
<?xml version="1.0" encoding="UTF-8"?><beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:osgi="http://www.springframework.org/schema/osgi"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/osgi http://www.springframework.org/schema/osgi/spring-osgi.xsd">
<osgi:service id="messageServiceOsgi" ref="messageService"
interface="org.osminog.service.MessageService" />
</beans>
Мы имеем два модуля, первый экспортирует интерфейс, второй модуль создает его реализацию и создает сервис, который будет использовать наш третий модуль, являющийся веб-приложением.
Третий модуль состоит из одного контроллера:
***
*/
package org.osminog.web;
import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;
import org.osminog.service.MessageService;import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.AbstractController;
*** @author Alexander Galibey
*
*/
public class MessageController extends AbstractController {
***
*/
private static final long serialVersionUID = 1L;
private MessageService messageService;
public MessageController() {
}
public MessageService getMessageService() {return messageService;
}
public void setMessageService(MessageService messageService) {this.messageService = messageService;
}
protected ModelAndView handleRequestInternal(HttpServletRequest arg0,HttpServletResponse arg1) throws Exception {
ModelAndView mav = new ModelAndView("echo.jsp");mav.addObject("message", messageService.getMessage());
return mav;
}
}
Контекста, который находит обьявленный ранее сервис, и назначает его нашему контролллеру.
<?xml version="1.0" encoding="UTF-8"?><beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:osgi="http://www.springframework.org/schema/osgi"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/osgi http://www.springframework.org/schema/osgi/spring-osgi.xsd">
<beanclass="org.springframework.web.servlet.mvc.support.ControllerClassNameHandlerMapping">
</bean>
<bean id="messageController"class="org.osminog.web.MessageController">
<property name="messageService" ref="messageService">
</property>
</bean>
<osgi:reference id="messageService" interface="org.osminog.service.MessageService"/>
</beans>
В web.xml мы подключаем контекс-класс OsgiBundleXmlWebApplicationContext:
<?xml version="1.0" encoding="ISO-8859-1"?><web-app xmlns="http://java.sun.com/xml/ns/j2ee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"
version="2.4">
<display-name>Simple OSMinog WebApp Bundle</display-name><description>Simple OSMinog War</description>
<welcome-file-list><welcome-file>index.html</welcome-file>
</welcome-file-list>
<servlet><servlet-name>osminog</servlet-name>
<servlet-class>
org.springframework.web.servlet.DispatcherServlet
</servlet-class>
<load-on-startup>2</load-on-startup>
<init-param>
<param-name>contextClass</param-name>
<param-value>
org.springframework.osgi.web.context.support.OsgiBundleXmlWebApplicationContext
</param-value>
</init-param>
</servlet>
<servlet-mapping><servlet-name>osminog</servlet-name>
<url-pattern>*.do</url-pattern>
</servlet-mapping>
</web-app>
В файле манифеста мы импортируем все библиотеки, необходимые для работы:
Web-ContextPath: WebModuleBundle-ManifestVersion: 2
Bundle-Name: Simple OSMinog War
Bundle-SymbolicName: org.osminog.web
Bundle-Classpath: .,/WEB-INF/classes
Import-Package: javax.servlet;version="2.4.0",
javax.servlet.http;version="2.4.0",
javax.servlet.resources;version="2.4.0",
javax.servlet.jsp;version="2.0.0",
javax.servlet.jsp.jstl.core;version="1.1.2",
javax.servlet.jsp.jstl.fmt;version="1.1.2",
javax.servlet.jsp.jstl.tlv;version="1.1.2",
org.apache.taglibs.standard.resources;version="1.1.2",
org.apache.taglibs.standard.tag.common.core;version="1.1.2",
org.apache.taglibs.standard.tag.rt.core;version="1.1.2",
org.apache.taglibs.standard.tei;version="1.1.2",
org.apache.taglibs.standard.tlv;version="1.1.2",
org.osminog.service,
org.springframework.web.servlet;version="[2.5.5,2.5.5.A]",
org.springframework.osgi.web.context.support;version="[1.1.0,1.1.0]",
org.springframework.web.servlet.mvc.support;version="[2.5.5,2.5.5.A]",
org.springframework.web.servlet.mvc;version="[2.5.5,2.5.5.A]",
org.springframework.web;version="[2.5.5,2.5.5.A]",
org.springframework.web.servlet.view;version="[2.5.5,2.5.5.A]"
Версия манифеста должна быть 2, чтоб экстендер понял что это веб-приложение, и classpath необходимо задать.
В echo.jps просто выводим полученную строку:
<?xml version="1.0" encoding="utf-8" ?><%@ page language="java" contentType="text/html; charset=utf-8"
pageEncoding="utf-8"%>
<html><body>
Message: ${message}
</body>
</html>
В конечном итоге должны получить Message: hello world!.
Автор: Alexander Galibey
| Комментарии к статье "Веб Приложение на ОСГИ" (1) |
| 04-08-2008 17-49 Отличная статья!!!! Спасибо автору |