Java / Статьи / Главная страница
04-08-2008

Веб Приложение на ОСГИ

Технология OSGi позволяет создавать модульные приложения, которое легко может конфигурироваться путем добавления,удаления или обновления модулей. В данном примеры мы рассмотрим создания простейшего веб-приложения как часть (модуль) другого приложения, основанного на OSGi

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.0

Bundle-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">

 


<bean

class="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: WebModule

Bundle-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)

Dmytriy L

04-08-2008 17-49 Отличная статья!!!! Спасибо автору


Вам есть, что сказать?




  Введите код