Java Web Application Integration OSGi

Source: Internet
Author: User
Tags web services java web

A simple understanding of OSGi

Just like a Java Web application needs to run in a container such as Tomcat, WebLogic. The OSGi packages developed by programmers also need to be run in OSGi containers. Currently, the main OSGi containers include Apache Felix and Eclipse Equinox. OSGi packages are called in OSGi Bundle . Bundlethe entire life cycle is managed by the OSGi container. You can Bundle implement a hot deployment by loading and unloading without stopping the service. It Bundle 's a black box for an external program. He simply registers the service interface for external invocation into the OSGi container, and the implementation is not visible to the outside. Bundlecalls between the different, also need to be implemented through the OSGi container.

How Bundles introduce jars

Just now Bundle it was a black box, and all of his implementations were wrapped up in the box. In the development Bundle , you can not avoid quoting some such as spring, Apache Commons and other open source packages. In order to Bundle package, you can package the current Bundle dependent jar with Bundle The source code is packaged into a package (All-in-one). The result of this package is that the package is too large, often a few trillion or more than 10 trillion, so of course we are unacceptable. A better approach is described below.

Bundle and OSGi container contract

___ Bundle can declare in the MANIFEST.MF configuration file The packages he wants to run and the versions of those packages!!! The OSGi container, Bundle when loaded, Bundle provides the Bundle required package!!! ___ When starting an OSGi container, you need to define the properties in the OSGi configuration file org.osgi.framework.system.packages.extra . This property defines the package that the OSGi container can provide and the version of the package . When OSGi loads Bundle , it will match the packages that he can provide and the packages and version lists that the bundle needs. If the match is unsuccessful, the exception is thrown directly:

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

It may also load Bundle through, but run Bundle times ClassNotFoundException . These exceptions are caused by configuration files that are not configured. Understanding the configuration file configuration method, you can resolve 60% of the exception.

Import-package

The Bundle properties in are configured in the Import-Package following format:

<!-- Pom.xml  - < Import-package > Javax.servlet,javax.servlet.http,org.xml.sax.*,org.springframework.beans.factory.xml;o Rg.springframework.beans.factory.config;version=4.1.1.release,org.springframework.util.*;version= "[2.5,5.0]"  </import-package>

    • Separated by commas between packages and packages
    • You can use a wildcard character such as this to represent all packages under this package. If you do not want to use wildcards, the other packages under the same package can be delimited with each other ; .
    • If you need to specify a version of the package, add it after the package ;version="[最低版本,最高版本]" . Where the [ representation is greater than or equal, ] represents less than or equal, and ) represents less than.
Org.osgi.framework.system.packages.extra

The syntax is Impirt-Package consistent with the basic, but org.osgi.framework.system.packages.extra wildcard characters are not supported.

    • The wrong way
Org.springframework.beans.factory.*;version=4.1.1.release

  

    • The right way:
Org.springframework.beans.factory.xml;org.springframework.beans.factory.config;version=4.1.1.release,

class file loading

In our usual development there are some cases where loading a class will be used this.getClassLoader().loadClass . However, the class that is written in this method Bundle class will fail and will be reported ClassNotFoundException . BundleReplace the method when you need to use the following classLoader.loadClass methods

public void Start (Bundlecontext context) throws Exception {     Class ClassType = context.loadclass (name);}

  

Issues when loading spring configuration files in bundles

Because Bundle Class of the loaded attributes, it causes the spring profile to load in the wrong times. So you need to change the classloader required for spring to start, making it call BundleContext.loadClass to load class.

String Xmlpath = ""; ClassLoader ClassLoader=NewClassLoader (Classutils.getdefaultclassloader ()) {@Override PublicClass<?> loadclass (String name)throwsClassNotFoundException {Try {            returnCurrentbundle.loadclass (name); } Catch(ClassNotFoundException e) {return Super. LoadClass (name);    }    }    }; Defaultlistablebeanfactory beanfactory=Newdefaultlistablebeanfactory ();    Beanfactory.setbeanclassloader (ClassLoader); Genericapplicationcontext CTX=NewGenericapplicationcontext (beanfactory);    Ctx.setclassloader (ClassLoader); Defaultresourceloader Resourceloader=NewDefaultresourceloader (classLoader) {@Override Public voidSetclassloader (ClassLoader ClassLoader) {if( This. getClassLoader () = =NULL) {                Super. Setclassloader (ClassLoader);    }        }    };    Ctx.setresourceloader (Resourceloader); Xmlbeandefinitionreader Reader=NewXmlbeandefinitionreader (CTX);    Reader.loadbeandefinitions (Xmlpath); Ctx.refresh ();

Web Application Integration OSGi

This has been chosen Apache Felix to develop, mainly because Apache Felix it is the top-level project of Apache. Community active, support for OSGi functionality is complete, and documentation examples are more comprehensive. In fact, OSGi supports two ways of deploying Bundle .

    • Deploy OSGi containers separately and provide Web services externally via OSGi's own web middleware (currently only jetty)
    • Embed OSGi containers in a web app, then use middleware such as WebLogic to run web Apps

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

Bundleactivator Development

Development Bundle , you need to develop one first BundleActivator . When OSGi is loaded Bundle , the method that is called first is BundleActivator start Bundle initialized. When unloaded Bundle , methods are called stop to release the resource.

 Public void throws Exception;  Public void throws Exception;

Called in the start method context.registerService to complete the registration of the external service.

New Hashtable ();p rops.put(new string[]{"/login", "/logout"= Context.registerservice ( Servlet. class New Dispatcherservlet (), props);

    • The first parameter of the Context.registerservice method represents the type of service, because we provide a Web request service, so the service type here is one javax.servlet.Servlet , so you need to javax.servlet.Servlet pass in the method
    • The second parameter is the service processing class, where a routing servlet is configured, followed by a corresponding program to process the specific request.
    • The third parameter is a Bundle property that provides services externally. In the example, the Hashtable support is defined in Bundle servlet-pattern . The web app where the OSGi container is located Bundle servlet-pattern determines whether customer requests are distributed to this by definition Bundle . servlet-patternThis name is random, not the name required by the OSGi framework.
Application Services Integrated OSGi container
    • First the project needs to add the following dependencies
 <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>

    • Then add in the web.xml
  < Listener >        < Listener-class >org.apache.felix.http.proxy.ProxyListener</listener-class>    </listener>

    • Developed ServletContextListener to initialize and launch the OSGi container, please refer Apache Felix to the example program provided. The examples provided in the ProvisionActivator package that will scan /WEB-INF/bundles/ and load them Bundle . (Of course, the provisionactivator provided in the example do not Bundle have mechanisms such as Autodiscover registration, which need to be increased on their own.) Please refer to the subsequent bundle auto-load section)
Routing development

With the above configuration, only the OSGi container is loaded into the Web application. You also need to modify the code for the Web application route.

  • Bundleafter being loaded into the OSGi container, you can bundleContext.getBundles() get all the loaded in the OSGi container by means of the method Bundle .
  • A method that can be called Bundle bundle.getRegisteredServices() to obtain Bundle all the service services that are provided externally. getRegisteredServices ServiceReference The array returned by the method. In the preceding article we call context.registerService(Servlet.class, new DispatcherServlet(), props) we have registered a service that getRegisteredServices returns only one object for the data ServiceReference .
  • Gets the value that can be supplied by the method in the Bundle ServiceReference object that getProperty gets context.registerService passed in props . This allows us ServiceReference.getProperty to obtain the Bundle services that can be provided by invoking the method.
  • Through the interface provided above, we can Bundle cache the corresponding ServiceReference and Bundle corresponding servlet-pattern . When the user requests to enter the application server, through the cache servlet-pattern can determine Bundle whether to provide the service requested by the user, if you can provide the following way to invoke the Bundle service provided.
servicereference sr =this. Bundlecontext.getservice (SR); Servlet.service (request, response);

Bundle Automatic Loading

In the Apache Felix example provided ProvisionActivator , only the directory is loaded at system startup /WEB-INF/bundles/ Bundle . When the files under the folder Bundle are updated, the OSGi container is not automatically updated Bundle . So Bundle the logic of automatic loading needs our own increase. Here are some ideas for implementation:

    • When the folder is loaded for the first time Bundle , the Bundle last update time corresponding to the package is recorded.
    • Create a separate thread in the program to scan the /WEB-INF/bundles/ directory, comparing Bundle the update time by one. If it is not in memory, get the object from OSGi Bundle and then call it and the stop uninstall method to unload it from the OSGi container.
    • After uninstalling, then invoking bundleContext.installBundle and bundle.start loading the latest Bundle into the OSGi container
Bundlelistener

The last problem, by the way above, can be implemented Bundle by automatic loading. But just now we've introduced that in the routing program, we cache all the corresponding and all the corresponding in the OSGi container Bundle ServiceReference Bundle servlet-pattern . So Bundle after Automatic Updates, we also need to update the cache in the routing program synchronously. bundleContext BundleListener Bundle BundleListener The callback method that can be called when the state in the OSGi container is updated by registering in bundleChanged . Then we can bundleChanged write the logic to update the route cache in the callback method

this. Bundlecontext.addbundlelistener (new  Bundlelistener () {    @Override      publicvoid  bundlechanged (bundleevent event) {        if (event.gettype () = =  bundleevent.started) {            initbundle (Event.getbundle ());         Else if (Event.gettype () = = bundleevent.uninstalled)            {= event.getbundle (). Getsymbolicname ();            Indexes.remove (name);        }     } });

Java Web Application Integration OSGi

Related Article

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.