2011年5月5日 星期四

OSGi&Wicket - To locate class and resource in bundle context.

在Osgi Container 裡面把Spring + Wicket 整合在一起,再用Spring Dm管理bundle
在這邊要針對Wicket做一些處理才能讓Wicket知道Bundle class & resource

Wicket 的WebApplication.mountBookmarkablePage("/home",home.class)
會mount一個page , 在localhost:8080/home
但home page在OSgi Bundle裡時,wicket是沒辦法認得的
這邊要做一些處理才能達成

首先建立一個Project OSGiWebApp2.Interface

MANIFEST.mf 檔
Manifest-Version: 1.0
Export-Package: com.osgiweb.apps2.OSGiWebApp2.Interface;version="1.0.0
 ";uses:="org.apache.wicket.markup.html.panel,org.apache.wicket.reques
 t.target.coding,org.apache.wicket.util.lang"
Unversioned-Imports: *
Built-By: momo
Tool: Bnd-1.15.0
Bundle-Name: Spring OSGi Bundle
Created-By: Apache Maven Bundle Plugin
Bundle-Version: 1.0.0
Build-Jdk: 1.6.0_24
Bnd-LastModified: 1304487240640
Bundle-ManifestVersion: 2
Import-Package: org.apache.wicket.markup.html.panel,org.apache.wicket.
 request.target.coding,org.apache.wicket.util.lang
Bundle-SymbolicName: com.osgiweb.apps2.OSGiWebApp2.Interface


IWicketPageService.java
package com.osgiweb.apps2.OSGiWebApp2.Interface;

import org.apache.wicket.Page;
import org.apache.wicket.request.target.coding.IRequestTargetUrlCodingStrategy;
import org.apache.wicket.util.lang.PackageName;

public interface IWicketPageService {

 /**
  * Mounts an encoder at the given path.
  * 
  * @param encoder
  *            the encoder that will be used for this mount
  */
 void mount(IRequestTargetUrlCodingStrategy encoder);

 /**
  * Mounts all bookmarkable pages at the given path.
  * 
  * @param path
  *            the path to mount the bookmarkable page class on
  * @param packageName
  *            the name of the package for which all bookmarkable pages or
  *            sharedresources should be mounted
  */
 void mount(final String path, final PackageName packageName);

 /**
  * Mounts a bookmarkable page class to the given path.
  * 
  * @param <T>
  *            type of page
  * 
  * @param path
  *            the path to mount the bookmarkable page class on
  * @param bookmarkablePageClass
  *            the bookmarkable page class to mount
  */
 <T extends Page> void mountBookmarkablePage(final String path,
   final Class<T> bookmarkablePageClass);

 /**
  * Mounts a bookmarkable page class to the given pagemap and path.
  * 
  * @param <T>
  *            type of page
  * 
  * @param path
  *            the path to mount the bookmarkable page class on
  * @param pageMapName
  *            name of the pagemap this mount is for
  * @param bookmarkablePageClass
  *            the bookmarkable page class to mount
  */
 <T extends Page> void mountBookmarkablePage(final String path,
   final String pageMapName, final Class<T> bookmarkablePageClass);

 /**
  * Mounts a shared resource class to the given path.
  * 
  * @param path
  *            the path to mount the resource class on
  * @param resourceKey
  *            the shared key of the resource being mounted
  */
 void mountSharedResource(final String path, final String resourceKey);

 /**
  * Partly unmounts/ignores a path that normally would map to another mount
  * path. Like mount("/mypage", MyPage.class); and then "/mypage/arealdir"
  * should be ignored. This can be done by calling
  * unMount("/mypage/arealdir");
  * 
  * @param path
  *            the path that should be ignored.
  * 
  */
 void addIgnoreMountPath(String path);

 /**
  * Unmounts whatever encoder is mounted at a given path.
  * 
  * @param path
  *            the path of the encoder to unmount
  */
 void unmount(String path);
}



然後再來建立一個Wicket Page Bundle Project, OSGiWebApp2.HomePages,
主要是存放一個Wicket Page

Activator.java , 這邊要參考OSGi Service by Interface IWicketPageService
透過這個service 通知WebApplication Bundle 我們mount 了一個bookmarkpage
package com.osgiweb.apps2.OSGiWebApp2.HomePages;

import org.osgi.framework.BundleContext;
import org.springframework.osgi.context.BundleContextAware;

import com.osgiweb.apps2.OSGiWebApp2.Interface.IWicketPageService;

public class Activator implements BundleContextAware {
 private BundleContext bundleCtx;
 IWicketPageService wicketService;
 
 public void start(){
  
  //ountBookmarkablePage(context, "page1", MyPage1.class);
  System.out.println("bundle stat ");
  wicketService.mountBookmarkablePage( "home2", home2.class);  
 }
 
 public void stop(){
  
 }


 public void setWicketService(IWicketPageService wicketService) {
  System.out.println("wicketService =" wicketService);
  this.wicketService = wicketService;
 }

 public void setBundleContext(BundleContext bundleContext) { 
  System.out.println("bundleCtx =" bundleCtx);
  this.bundleCtx = bundleContext;
  
 }
}

hom2.java
package com.osgiweb.apps2.OSGiWebApp2.HomePages;

import org.apache.wicket.markup.html.WebPage;
import org.apache.wicket.markup.html.basic.Label;


public class home2 extends WebPage {
// private IuserDaoImp dao = new IuserDaoImp();
    /**
     * Constructor
     */
    public home2()
    { 
     System.out.println("test for remort home2");
//        add(new Label("message", "Hello OSGi-land! ffff" dao.selectUserName()));
     add(new Label("message","Hello"));
    }
}

home2.html
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
    <head>
        <title>Wickety OSGi!</title>
    </head>
    <body>
     Replace SSS
        <p wicket:id="message">replace me</p>
    </body>
</html>

bundle-context-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">

  <!-- definitions using elements of the osgi namespace can be included
       in this file. There is no requirement to keep these definitions
       in a separate file if you do not want to. The rationale for 
       keeping these definitions separate is to facilitate integration
       testing of the bundle outside of an OSGi container -->
       <osgi:reference id="iwicketService" interface="com.osgiweb.apps2.OSGiWebApp2.Interface.IWicketPageService"/>
</beans>

bundle-context.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">

 <!-- regular spring configuration file defining the beans for this bundle. 
  The configuration of OSGi definitions is kept in a separate configuration 
  file so that this file can easily be used for integration testing outside 
  of an OSGi environment -->
 <bean id="actavitor" class="com.osgiweb.apps2.OSGiWebApp2.HomePages.Activator"
  init-method="start" destroy-method="stop">
  <property name="wicketService" ref="iwicketService" />
 </bean>
</beans>

MANIFEST.MF
Manifest-Version: 1.0
Export-Package: com.osgiweb.apps2.OSGiWebApp2.HomePages;version="1.0.0";
  uses:="com.osgiweb.apps2.OSGiWebApp2.Interface,
   org.apache.wicket.markup.html,
   org.osgi.framework,
   org.springframework.osgi.context"
Unversioned-Imports: *
Built-By: momo
Tool: Bnd-1.15.0
Bundle-Name: Spring OSGi Bundle
Created-By: Apache Maven Bundle Plugin
Bundle-Version: 1.0.0
Build-Jdk: 1.6.0_24
Bnd-LastModified: 1304478929625
Bundle-ManifestVersion: 2
Import-Package: com.osgiweb.apps2.OSGiWebApp2.Interface,
 org.apache.wicket,
 org.apache.wicket.markup.html,
 org.apache.wicket.markup.html.basic,
 org.osgi.framework,
 org.springframework.osgi.context
Bundle-SymbolicName: com.osgiweb.apps2.OSGiWebApp2.HomePages

再來就是最主要的Web Domain Bundle ,
這邊建立一個Web Bundle projectd , OSGiWebApp2.web

首先要建立Web.xml 設定
<?xml version="1.0" encoding="ISO-8859-1"?>
<web-app xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" version="2.5">

  <display-name>OSGiWebApp - web</display-name>
  
  
  <context-param>
    <param-name>contextClass</param-name>
    <param-value>org.eclipse.virgo.web.dm.ServerOsgiBundleXmlWebApplicationContext</param-value>
  </context-param>

  <listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
  </listener>
 
 <filter>
  <filter-name>WicketSpring</filter-name>
  <filter-class>org.apache.wicket.protocol.http.WicketFilter</filter-class>
  <init-param>
   <param-name>applicationFactoryClassName</param-name>
   <param-value>org.apache.wicket.spring.SpringWebApplicationFactory</param-value>
  </init-param>
 </filter>

<filter-mapping>
 <filter-name>WicketSpring</filter-name>
 <url-pattern>/*</url-pattern>
 <dispatcher>REQUEST</dispatcher>
 <dispatcher>ERROR</dispatcher>
</filter-mapping>

  <!-- DISPATCHER SERVLET CONFIG ,Spring MVC -->
  <!-- 
  <servlet>
    <servlet-name>greenpages</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
  </servlet>

  <servlet-mapping>
    <servlet-name>greenpages</servlet-name>
    <url-pattern>/app/*</url-pattern>
  </servlet-mapping>
   -->
   
   
</web-app>

然後是Spring XML cofnig , applicationContext.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
  http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
  http://www.springframework.org/schema/osgi http://www.springframework.org/schema/osgi/spring-osgi.xsd"
 xmlns:context="http://www.springframework.org/schema/context"
 xmlns:osgi="http://www.springframework.org/schema/osgi">
 
  <!-- enable classpath scanning -->
 <context:component-scan base-package="OSGiWebApp.web" />
 
 <bean class="org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor"/>
 <!-- enable anntotation-driven controllers -->
 <bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter" />
 
 <bean id="wicketApplication" class="com.app.WicketApplication">
 </bean>
</beans>

WicketApplication.java extends WebApplication, 在init的時候還要設定一下一些屬性
因為原本的Wicket 是不支援OSGi classpath & resource , 在init 的時候要設定
1: this.getApplicationSettings().setClassResolver(final IClassResolver defaultClassResolver)
2: this.getResourceSettings().setResourceStreamLocator(IResourceStreamLocator resourceStreamLocator);
3: registerPageService(this);
(從這邊init時也要把Interface IWicketPageService 註冊成OSGi Service, 實作為WicketPageServiceImpl
確保Bundle 在mountbookmarkpage時的WebApplication 都為同一個)
Update(05/11): 設定好setClassResolver,setResourceStreamLocator之後,可直接對package class做處理, Example :
...
setResponsePage(com.osgiweb.apps2.OSGiWebApp2.HomePages.home2.class);
..
..
WicketApplication.java
package com.app;

import org.apache.wicket.Page;
import org.apache.wicket.protocol.http.WebApplication;
import org.apache.wicket.spring.injection.annot.SpringComponentInjector;
import com.osgi.OsgiResourceStreamLocator;
import org.osgi.framework.BundleContext;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.osgi.context.BundleContextAware;
import org.springframework.stereotype.Component;

import com.osgi.OsgiClassResolver;
import com.osgiweb.apps2.OSGiWebApp2.Interface.IWicketExtensionService;
import com.osgiweb.apps2.OSGiWebApp2.Interface.IWicketPageService;
import com.page.home;
import com.service.WicketExtensionServiceImpl;
import com.service.WicketPageServiceImpl;


@Component
public class WicketApplication extends WebApplication implements ApplicationContextAware,BundleContextAware{
 private static final String DEFAULT_ENCODING = "UTF-8";
 
 private BundleContext bundleCtx;
 
 @Autowired
    private ApplicationContext applicationContext;


 @Override
    public Class<? extends Page> getHomePage() {
   
        return home.class;
    }
 protected void init() {      
     this.getApplicationSettings().setClassResolver(new OsgiClassResolver());
     this.getResourceSettings().setResourceStreamLocator(new OsgiResourceStreamLocator());
//     this.getPageSettings().addComponentResolver(new OsgiExtensionPointResolver());
     super.init();          
     
     addComponentInstantiationListener(new SpringComponentInjector(this, applicationContext, true));
     getMarkupSettings().setDefaultMarkupEncoding(DEFAULT_ENCODING);    
     registerPageService(this);
     
 }
 
 
 
// @Override
//    public String getConfigurationType() {
//        return WebApplication.DEVELOPMENT;
//    }
 
 @Override
 public void setApplicationContext(ApplicationContext applicationContext)
   throws BeansException {
  
   this.applicationContext = applicationContext;
  
 }
// public static WicketApplication get() {
//        return (WicketApplication) WebApplication.get();
//    }
 
 
 
 @Override
 public void setBundleContext(BundleContext bundleContext) {
  this.bundleCtx = bundleContext;
  System.out.println("bundle ctx = " bundleCtx );
 }
 
 public void registerPageService(WebApplication app){
  System.out.println("register pageService");
  System.out.println("class = "  IWicketPageService.class.getName());
  this.bundleCtx.registerService(IWicketPageService.class.getName(), new WicketPageServiceImpl(this), null);
  System.out.println("register pageService finished");
  
  this.bundleCtx.registerService(IWicketExtensionService.class.getName(),new WicketExtensionServiceImpl(), null);
 }
 
 
} 


然後是OsgiClassResolver.java , 實作IClassResolver , 針對OSGi 改寫resolveClass
package com.osgi;

import java.net.URL;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;

import org.apache.wicket.application.DefaultClassResolver;
import org.apache.wicket.application.IClassResolver;
import org.apache.wicket.util.string.Strings;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleContext;
import org.springframework.osgi.context.BundleContextAware;

public class OsgiClassResolver implements IClassResolver,BundleContextAware {

 private DefaultClassResolver wrappedClassResolver;
 private BundleContext bundleCtx;
 
 public OsgiClassResolver() {
  this.wrappedClassResolver = new DefaultClassResolver();
 }

 /**
  * {@inheritDoc}
  * 
  * @see org.apache.wicket.application.IClassResolver#getResources(java.lang.String)
  */
 public Iterator<URL> getResources(String name) {
  System.out.println("to get Resources = "  name);
  return this.wrappedClassResolver.getResources(name);
 }

 /**
  * {@inheritDoc}
  * 
  * @see org.apache.wicket.application.IClassResolver#resolveClass(java.lang.String)
  */
 public Class<?> resolveClass(String classname)
   throws ClassNotFoundException {
  System.out.println("resolveClass = "   classname);
  Class<?> clazz = null;

  try {

   clazz = this.wrappedClassResolver.resolveClass(classname);

  } catch (ClassNotFoundException e) {

   // not found in parent classloader? look through the bundles...
   System.out.println("resolveClass for bundles");
   Bundle[] bundles = bundleCtx.getBundles();
   if (bundles != null && bundles.length > 0) {
    for (Bundle bundle : bundles) {

     if (bundle.getState() != Bundle.ACTIVE
       || !this.classIsExportedByBundle(classname, bundle))
      continue;

     try {
      clazz = bundle.loadClass(classname);
      if (clazz != null)
       break;
     } catch (ClassNotFoundException ex) {
      ; // ignore and try next bundle..
     }
    }
   }

  }

  if (clazz == null)
   throw new ClassNotFoundException(classname);

  return clazz;
 }

 private boolean classIsExportedByBundle(String classname, Bundle bundle) {
  List<String> exportedPackages = this.getExportedPackages(bundle);
  return exportedPackages.contains(Strings.beforeLast(classname, '.'));
 }

 private List<String> getExportedPackages(Bundle bundle) {
  String exportedString = (String) bundle.getHeaders().get(
    "Export-Package");
  if (Strings.isEmpty(exportedString))
   return Collections.emptyList();

  String[] splitted = Strings.split(exportedString, ',');
  if (splitted == null || splitted.length == 0)
   return Collections.emptyList();

  List<String> packages = new ArrayList<String>();
  for (String s : splitted) {
   String pkg = null;
   if (s.contains(";"))
    pkg = Strings.beforeFirst(s, ';').trim();
   else
    pkg = s.trim();

   if (pkg != null && pkg.length() > 0)
    packages.add(pkg);
  }

  return packages;
 }

 @Override
 public void setBundleContext(BundleContext bundleContext) {
  this.bundleCtx = bundleContext;
  
 }
}


然後是OsgiResourceStreamLocator.java(org.apache.wicket.util.resource.locator下有自帶一個)
package com.osgi;

import org.apache.wicket.util.file.IResourceFinder;
import org.apache.wicket.util.resource.IResourceStream;
import org.apache.wicket.util.resource.locator.ResourceStreamLocator;

/**
 * OSGI specific resource stream factory
 * 
 * @author Juergen Donnerstag
 */
public class OsgiResourceStreamLocator extends ResourceStreamLocator
{
 /**
  * Construct.
  */
 public OsgiResourceStreamLocator()
 {
 }

 /**
  * Construct.
  * 
  * @param finder
  */
 public OsgiResourceStreamLocator(final IResourceFinder finder)
 {
  super(finder);
 }

 /**
  * 
  * @see org.apache.wicket.util.resource.locator.ResourceStreamLocator#locate(java.lang.Class,
  *      java.lang.String)
  */
 @Override
 public IResourceStream locate(final Class<?> clazz, final String path)
 {
  System.out.println("IResourceStream = " clazz ", path-" path);
  return super.locate(clazz, "/"   path);
 }
}


WicketPageServiceImpl.java , 這邊主要呼叫WebApplication 下的mount,mountBookmarkablePage
在Web Domain Bundle 啟動初始化同時建立一個OSGi Service , 內含WebApplication實體一個
其他Bundle 透過mountBookmarkablePage告知Web Domain Bundle 新的Page Bundle 資訊
package com.service;

import org.apache.wicket.Page;
import org.apache.wicket.protocol.http.WebApplication;
import org.apache.wicket.request.target.coding.IRequestTargetUrlCodingStrategy;
import org.apache.wicket.util.lang.PackageName;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import com.osgiweb.apps2.OSGiWebApp2.Interface.IWicketPageService;
/**
 * Default implementation of the {@link IWicketPageService} interface.
 * 
 * 
 * 
 */
public class WicketPageServiceImpl implements IWicketPageService {

 private WebApplication application;

 public WicketPageServiceImpl(WebApplication application) {
  this.application = application;
 }

 /**
  * {@inheritDoc}
  * 
  * @see net.javaforge.wicket.osgi.service.IWicketPageService#addIgnoreMountPath(java.lang.String)
  */
 public void addIgnoreMountPath(String path) {
  this.application.addIgnoreMountPath(path);
 }

 /**
  * {@inheritDoc}
  * 
  * @see net.javaforge.wicket.osgi.service.IWicketPageService#mount(org.apache.wicket.request.target.coding.IRequestTargetUrlCodingStrategy)
  */
 public void mount(IRequestTargetUrlCodingStrategy encoder) {
  this.application.mount(encoder);

 }

 /**
  * {@inheritDoc}
  * 
  * @see net.javaforge.wicket.osgi.service.IWicketPageService#mount(java.lang.String,
  *      org.apache.wicket.util.lang.PackageName)
  */
 public void mount(String path, PackageName packageName) {
  this.application.mount(path, packageName);
 }

 /**
  * {@inheritDoc}
  * 
  * @see net.javaforge.wicket.osgi.service.IWicketPageService#mountBookmarkablePage(java.lang.String,
  *      java.lang.Class)
  */
 public <T extends Page> void mountBookmarkablePage(String path,
   Class<T> bookmarkablePageClass) {
  System.out.println("mountBookmarkablePage 77");
  this.application.mountBookmarkablePage(path, bookmarkablePageClass);

 }

 /**
  * {@inheritDoc}
  * 
  * @see net.javaforge.wicket.osgi.service.IWicketPageService#mountBookmarkablePage(java.lang.String,
  *      java.lang.String, java.lang.Class)
  */
 public <T extends Page> void mountBookmarkablePage(String path,
   String pageMapName, Class<T> bookmarkablePageClass) {
  System.out.println("mountBookmarkablePage 90");
  System.out.println("Path = " path);
  System.out.println("pageMapName = " pageMapName);
  System.out.println("bookmarkablePageClass = " bookmarkablePageClass);
  this.application.mountBookmarkablePage(path, pageMapName,
    bookmarkablePageClass);

 }

 /**
  * {@inheritDoc}
  * 
  * @see net.javaforge.wicket.osgi.service.IWicketPageService#mountSharedResource(java.lang.String,
  *      java.lang.String)
  */
 public void mountSharedResource(String path, String resourceKey) {
  this.application.mountSharedResource(path, resourceKey);

 }

 /**
  * {@inheritDoc}
  * 
  * @see net.javaforge.wicket.osgi.service.IWicketPageService#unmount(java.lang.String)
  */
 public void unmount(String path) {
  this.application.unmount(path);

 }

 public void setApplicationContext(ApplicationContext applicationContext)
   throws BeansException {
  // TODO Auto-generated method stub
  
 }

}

home.java , 已mount的page 可以直接在Broswer 輸入localhost:8080/mountPageName
或著使用setResponsePage(com.osgiweb.apps2.OSGiWebApp2.HomePages.home2.class)
package com.page;

import org.apache.wicket.markup.html.WebPage;
import org.apache.wicket.markup.html.basic.Label;

public class home extends WebPage {
 // private IuserDaoImp dao = new IuserDaoImp();
 /**
  * Constructor
  */
 public home() {
  System.out.println("test for homePage 2");
  // add(new Label("message",
  // "Hello OSGi-land! ffff" dao.selectUserName()));
  add(new Label("message", "Hello"));  
  setResponsePage(com.osgiweb.apps2.OSGiWebApp2.HomePages.home2.class);
 }
}


home.html
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>Wickety OSGi!</title>
</head>
<body>
 <p wicket:id="message">replace me</p>
 
 
</body>
</html>


MANIFEST.mf
Manifest-Version: 1.0
Import-Bundle: com.springsource.org.apache.taglibs.standard;version="[
 1.1.2,1.3)"
Bundle-Version: 1.0.0
Tool: Bundlor 1.0.0.RELEASE
Bundle-Name: OSGiWebApp web
Import-Library: org.springframework.spring;version="[3.0,3.1)"
Bundle-ManifestVersion: 2
Bundle-SymbolicName: OSGiWebApp2.web 
Web-ContextPath: OSGiWebApp
Import-Package: javax.servlet.jsp.jstl.core;version="[1.1.2,1.2.0)",
 org.apache.wicket;version="1.4.16",
 org.apache.wicket.application;version="1.4.16",
 org.apache.wicket.markup.html;version="1.4.16",
 org.apache.wicket.markup.html.basic;version="1.4.16",
 org.apache.wicket.protocol.http;version="1.4.16",
 org.apache.wicket.settings;version="1.4.16",
 org.apache.wicket.spring;version="1.4.16",
 org.apache.wicket.spring.injection.annot;version="1.4.16",
 org.apache.wicket.markup.resolver;version="1.4.16",
 org.apache.wicket.util.file;version="1.4.16",
 org.apache.wicket.util.resource.locator;version="1.4.16",
 
 org.eclipse.virgo.web.dm;version="[2.0.0,3.0.0)",
 org.slf4j;version="1.6.1",
 org.springframework.beans;version="[3.0.0,3.1.0)",
 org.springframework.beans.factory.annotation;version="[3.0.0,3.1.0)",
 org.springframework.context;version="[3.0.0,3.1.0)",
 org.springframework.stereotype;version="[3.0.0,3.1.0)",
 org.springframework.web.servlet.mvc.annotation;version="[3.0.0,3.1.0)",
 org.springframework.osgi.context,
 com.osgiweb.apps2.OSGiWebApp2.Interface,
 com.osgiweb.apps2.OSGiWebApp2.HomePages
Export-Package: com.app;version="1.0.0";
  uses:="org.apache.wicket.protocol.http,
   org.osgi.framework,
   org.springframework.beans,
   org.springframework.beans.factory.annotation,
   org.springframework.context,
   org.springframework.osgi.context,
   org.springframework.stereotype",
 com.osgi;version="1.0.0";
  uses:="org.apache.wicket,
   org.apache.wicket.application,
   org.apache.wicket.markup,
   org.apache.wicket.markup.resolver,
   org.osgi.framework,
   org.springframework.osgi.context",
 com.page;version="1.0.0";uses:="org.apache.wicket.markup.html",
 com.service;version="1.0.0";
  uses:="com.osgiweb.apps2.OSGiWebApp2.Interface,
   org.apache.wicket.protocol.http,
   org.apache.wicket.request.target.coding,
   org.apache.wicket.util.lang,
   org.springframework.beans,
   org.springframework.context"


然後deploy到Server上 ,看看bundle狀況


輸入位置 http://localhost:8080/OSGiWebApp/
會看到OSGiWebApp2.HomePages 下的home2.html結果

查看server log, IResourceStream 會load resource from bundle class


Reference:
Pax Wicket

Wicket Osgi Extension

Wicket, OSGi, and Spring DM

沒有留言:

張貼留言