Java Web Application Integration OSGI

Source: Internet
Author: User

Java Web Application Integration OSGI
A simple understanding of OSGI

Just as Java Web applications need to run in containers such as Tomcat and Weblogic. OSGI packages developed by programmers also need to run in OSGI containers. Currently, mainstream OSGI containers include Apache Felix and Eclipse Equinox. The OSGI package is calledBundle.
BundleThe entire lifecycle is managed with the OSGI container. You canBundleLoad and detach to achieve hot deployment.
BundleIt is a black box for external programs. It only registers a service interface for external calls to the OSGI container, but is invisible to the external. DifferentBundleThe call between them also needs to be implemented through the OSGI container.

How to introduce jar into Bundle

As mentioned earlierBundleIt is a black box. All his implementations are packaged into his own "box. In developmentBundleYou cannot reference some open-source packages such as Spring and Apache commons. InBundleDuring packaging, you canBundleDependent jar andBundleThe source code is packaged into a package (all-in-one ). The packaging result is that the output package is too large, usually several megabytes or dozens of megabytes, which is unacceptable. The following describes a better method.

Contract between Bundle and OSGI container

BundleYou canMANIFEST.MFIn the configuration file, declare the packages he wants to run and the version of these packages !!! While the OSGI container is loadingBundleWill beBundleProvideBundleRequired package !!!When starting the OSGI container, You need to define it in the OSGI configuration fileorg.osgi.framework.system.packages.extra, Attribute. This property definesThe packages and packages available in the OSGI container. OSGI LoadingBundleThe packages that can be provided by the Bundle and the packages and version lists required by the Bundle are matched. If the matching fails, an exception is thrown:

Unable to execute command on bundle 248: Unresolved constraint in bundlecom.osgi.demo2 [248]: Unable to resolve 248.0: missing requirement [248.0] osgi.wiring.package; (&(osgi.wiring.package=org.osgi.framework)(version>=1.8.0)(!(version>=2.0.0)))

It may also loadBundlePass, but runBundleTimesClassNotFoundException. These exceptions are caused by the absence of configuration files. After understanding the configuration method of the configuration file, the 60% exception can be solved.

Import-Package

InBundleOfImport-PackageThe attribute is configured in the following format:

<!--pom.xml--> <Import-Package>javax.servlet,javax.servlet.http,org.xml.sax.*,org.springframework.beans.factory.xml;org.springframework.beans.factory.config;version=4.1.1.RELEASE,org.springframework.util.*;version="[2.5,5.0]"</Import-Package>
  • Separate packages with commas
  • You can use wildcard characters such as * to indicate all packages in this package. If you do not want to use wildcards, other packages under the same package can use one another.;Separated.
  • If you want to specify the version of the package, add; Version = "[minimum version, Maximum version]". Where[Equal to or greater,]Indicates less than or equal,)Indicates less.
Org. osgi. framework. system. packages. extra

Syntax andImpirt-PackageBasically consistent, justorg.osgi.framework.system.packages.extraWildcards are not supported.

  • Incorrect Method

    org.springframework.beans.factory.*;version=4.1.1.RELEASE
  • The correct method:

    org.springframework.beans.factory.xml;org.springframework.beans.factory.config;version=4.1.1.RELEASE,
Class file loading

In normal development, loading a Class will usethis.getClassLoader().loadClass. However, this method is used to loadBundleTheclassWill fail, will reportClassNotFoundException. InBundleUse the following method to replaceclassLoader.loadClassMethod

 public void start(BundleContext context) throws Exception {     Class classType = context.loadClass(name); }
Question about loading Spring configuration files in Bundle

BecauseBundleLoadClassWill cause errors when loading the Spring configuration file. Therefore, you need to change the ClassLoader required for Spring startup so that it can callBundleContext.loadClassTo load the Class.

String xmlPath = "";ClassLoader classLoader = new ClassLoader(ClassUtils.getDefaultClassLoader()) {    @Override    public Class<?> loadClass(String name) throws ClassNotFoundException {        try {            return currentBundle.loadClass(name);        } catch (ClassNotFoundException e) {            return super.loadClass(name);        }    }    };    DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();    beanFactory.setBeanClassLoader(classLoader);    GenericApplicationContext ctx = new GenericApplicationContext(beanFactory);    ctx.setClassLoader(classLoader);    DefaultResourceLoader resourceLoader = new DefaultResourceLoader(classLoader) {        @Override        public void setClassLoader(ClassLoader classLoader) {            if (this.getClassLoader() == null) {                super.setClassLoader(classLoader);            }        }    };    ctx.setResourceLoader(resourceLoader);    XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(ctx);    reader.loadBeanDefinitions(xmlPath);    ctx.refresh();
Web Application Integration OSGI

Selected hereApache FelixMainly becauseApache FelixIs a top-level project of Apache. Active Communities, complete support for OSGI functions, and comprehensive documentation examples.
Actually, OSGI supports two deployment methods.Bundle.

  • Independently deploy OSGI containers to provide external Web services through OSGI Web middleware (currently only jetty)
  • Embed OSGI containers into Web applications, and then use Weblogic and other middleware to run Web applications.

From the overall consideration of the project, we chose the second solution.

BundleActivator Development

DevelopmentBundleFirst, you need to developBundleActivator. OSGI LoadingBundleFirst, callBundleActivatorOfstartMethodBundle. DetachBundleWill callstopTo release the resource.

public void start(BundleContext context) throws Exception;public void stop(BundleContext context) throws Exception;

InstartMethod callcontext.registerServiceTo complete external service registration.

Hashtable props = new Hashtable();props.put("servlet-pattern", new String[]{"/login","/logout"})ServiceRegistration servlet = context.registerService(Servlet.class, new DispatcherServlet(), props);
  • The first parameter of the context. registerService method indicates the service type. Because we provide the Web request service, the service type here isjavax.servlet.Servlet, So you needjavax.servlet.ServletPassed in to Method
  • The second parameter is the service processing class. A routing Servlet is configured here, and a corresponding program will be used to process specific requests.
  • The third parameter isBundleAttributes of the external service. In the exampleHashtableDefined inBundleSupportedservlet-pattern. The Web application where the OSGI container is located passes throughBundleDefinedservlet-patternDetermine whether to distribute customer requests to thisBundle.servlet-patternThis name is random and is not the name required by the OSGI framework.
Application Service integration OSGI container
  • First, add the following dependencies to the project:
   <dependency>            <groupId>org.apache.felix</groupId>            <artifactId>org.apache.felix.framework</artifactId>            <version>5.6.10</version>        </dependency>        <dependency>            <groupId>org.apache.felix</groupId>            <artifactId>org.apache.felix.http.bundle</artifactId>            <version>3.0.0</version>        </dependency>        <dependency>            <groupId>org.apache.felix</groupId>            <artifactId>org.apache.felix.http.bridge</artifactId>            <version>3.0.18</version>        </dependency>        <dependency>            <groupId>org.apache.felix</groupId>            <artifactId>org.apache.felix.http.proxy</artifactId>            <version>3.0.0</version>        </dependency>
  • Thenweb.xmlAdd
    <listener>        <listener-class>org.apache.felix.http.proxy.ProxyListener</listener-class>    </listener>
  • DevelopmentServletContextListenerUsed to initialize and start the OSGI container
    SeeApache FelixProvided example program. TheProvisionActivatorYes/WEB-INF/bundles/, LoadBundlePackage. (Of course, The ProvisionActivator provided in this example does not containBundleAutomatic Discovery of registration and other mechanisms, these logics need to be added on their own. Refer to the subsequent automatic Bundle loading chapter)
Route Development

The above configuration only loads the OSGI container into the Web application. You also need to modify the Web application routing code.

  • InBundleAfter being loaded to the OSGI container, you can usebundleContext.getBundles()Obtain all the loadedBundle.
  • YesBundleOfbundle.getRegisteredServices()Method to obtainBundleAll external services.getRegisteredServicesMethod returnServiceReference. We callcontext.registerService(Servlet.class, new DispatcherServlet(), props)We have registered a service,getRegisteredServicesOnly one data is returned.ServiceReferenceObject.
  • ObtainBundleServices available
    You can useServiceReferenceObjectgetPropertyMethod acquisitioncontext.registerServicePassed inprops. In this way, we can callServiceReference.getPropertyMethod to obtainBundleThe service that can be provided.
  • Through the interface provided above, we canBundleCorrespondingServiceReferenceAndBundleCorrespondingservlet-patternCache. After a user request enters the application serverservlet-patternCan be judgedBundleWhether the Service requested by the user can be provided by callingBundleProvided services.
 ServiceReference sr = cache.get(bundleName); HttpServlet servlet = (HttpServlet) this.bundleContext.getService(sr); servlet.service(request, response);
Automatic Bundle Loading

InApache FelixTheProvisionActivator, Will only be loaded at system startup/WEB-INF/bundles/DirectoryBundle. WhenBundleWhen the file is updated,Bundle. SoBundleThe logic for automatic loading needs to be added by ourselves. The following provides implementation ideas:

  • For the first timeBundleTime, recordBundleThe last update time corresponding to the package.
  • Create an independent thread in the program for scanning/WEB-INF/bundles/Directory, compare them one by oneBundle. If it is inconsistent with the memory, it is obtained from OSGI.BundleObject and then call itsstopAnduninstallMethod To uninstall it from the OSGI container.
  • After uninstallation, callbundleContext.installBundleAndbundle.startAdd the latestBundleLoad to OSGI container
BundleListener

The last problem can be solved through the above method.Bundle. But as we introduced just now, in the routing program, we will cache allBundleCorrespondingServiceReferenceAnd allBundleCorrespondingservlet-pattern. SoBundleAfter automatic update, we also need to update the cache in the routing program synchronously.
You canbundleContextMedium RegistrationBundleListenerWhenBundleAfter the status is updatedBundleListenerOfbundleChangedCallback method. Then we canbundleChangedWrite the logic for updating the route cache in the callback Method

this.bundleContext.addBundleListener(new BundleListener() {    @Override    public void bundleChanged(BundleEvent event) {        if (event.getType() == BundleEvent.STARTED) {            initBundle(event.getBundle());        } else if (event.getType() == BundleEvent.UNINSTALLED) {            String name = event.getBundle().getSymbolicName();            indexes.remove(name);        }     } });

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.