Network Security Internet Technology Development Database Servers Mobile Phone Android Software Apple Software Computer Software News IT Information

In addition to Weibo, there is also WeChat

Please pay attention

WeChat public account

Shulou

Architecture Design-- OSGI Specification

2025-03-29 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Internet Technology >

Share

Shulou(Shulou.com)06/03 Report--

Architecture design-introduction to OSGI 1, introduction to OSGI 1, introduction to OSGI

OSGI (Open Service Gateway Initiative), the Open Service Gateway Protocol, is a dynamic model system oriented to Java.

OSGI refers to the Java modular specification developed by the OSGI Alliance organization. The core part of the OSGI specification is a framework that defines the life cycle pattern and service registration of the application. Based on the OSGI framework, a large number of OSGI services are defined: logging, configuration management, HTTP services (running Servlet), XML parsing, device access, software package management, license management, user management, IO connection, Jini and UPnP, etc.

OSGI Chinese Community: http://www.osgi.com.cn/

OSGI official website: https://www.osgi.org/

The OSGI framework implements an elegant, complete, and dynamic component model, and components (bundle) can be remotely installed, started, upgraded, and uninstalled without rebooting.

The OSGI service platform provides the ability to dynamically change the configuration without restarting on a variety of network devices.

In order to minimize the degree of coupling and make the coupling manageable, OSGI technology provides a service-oriented architecture that enables components to discover each other dynamically.

The OSGI Alliance has developed standard component interfaces for many common functions, such as HTTP server, configuration, logging, security, user management, XML, and so on. Compatibility plug-in implementations of standard components are available from different computer service providers.

The main responsibility of OSGi is to enable developers to create dynamic and modular Java systems.

2. The composition of OSGI specification.

The OSGI specification includes the following sub-specifications:

A, Framework specification (OSGI core, which provides a secure and manageable Java Framework to deploy scalable Java services)

B, Package Admin Service specification (manages the reference relationship between different Bundle. Determine whether other services are using the current Bundle when Bundle is updated or uninstalled)

C, Start Level specification (defines the order in which different OSGi Service Platform starts or stops when a Bundles is started and stopped)

D, Permission Admin Service specification (whether Bundle permits the execution of other Bundle code)

E, URL Handlers Service specification (how to register URL Schema, how to convert java.io.InputStream objects to specific Java objects)

F, Log Service specification

G, Configuration Admin Service specification

H 、 Device Access Specification

I 、 User Admin Service Specification

J 、 IO Connector Service Specification

K 、 Http Service Specification

L 、 Preference Service Specification

M 、 Wire Admin Service Specification

N 、 XML Parser Service Specification

O 、 Metatype Specification

P 、 Service Tracker Specification

Q 、 Measurment and State Specification

R 、 Position Specification

S 、 Execution Environment Specfication

3. Advantages of OSGI

The advantages of OSGI are mainly shown in the following aspects:

A. Plug-in architecture of hot plug

OSGI-based applications can dynamically change the running state and behavior. In the OSGI framework, every component is hot-swappable, so modifications to a particular component do not affect all components in the container, most of the running components still work as usual, and there is no need to restart the server when deploying a new Bundle.

B, reusability

The OSGI framework itself is highly reusable and easy to build a truly interface-oriented program architecture, and each Bundle is an independent reusable unit. Based on the unique characteristics of OSGI, when carrying out enterprise development, for new development, reusable modules can be streamlined from the enterprise component library, and new components can be tailored to maximize the use of existing resources, reduce development costs and enhance the competitiveness of enterprises.

C, efficiency, stability

OSGI is a stable and efficient system. As a micronucleus system, OSGI has only a few JAR packages in its core. Because of the low coupling of the system based on OSGI framework, the superiority of its structure ensures that a specific component will not affect the overall situation, let alone the collapse of the global system because of local errors.

4. Shortcomings of OSGI

A, each component (Bundle) is loaded by a separate class loader, so it is difficult to integrate with some frameworks that are widely used in Java EE projects, such as Spring MVC, Struts2 and so on.

B. At present, the management side provided by the OSGI framework is not strong enough. The current management side only provides basic functions such as component state management, log viewing, etc., such as dynamic modification of system level configuration (config.ini), dynamic modification of component configuration (Manifest.mf), startup level and other functions have not been provided.

C, the module development and deployment mode using OSGI as the specification naturally puts forward new requirements for existing developers, and they need to learn new development methods based on OSGI.

Second, the principle of OSGI framework 1. Brief introduction of OSGI framework

The OSGI framework can be conceptually divided into three layers: module layer, life cycle layer and service layer.

Module Layer: the module layer is mainly concerned with packages and shared code

Lifecycle Layer: the lifecycle layer is mainly concerned with runtime lifecycle management of components

Service Layer: the service layer is mainly concerned with the interaction and communication between modules.

OSGI Framework is a core component of the OSGI Service Platform specification, which provides a universal, secure and manageable Java framework. The deployment and extension of a Service application called components can be supported through OSGI Framework.

OSGI compatible devices can download and install OSGI components, or remove them once they are no longer needed. After installation, the component registers a certain number of Services and is used by other components under the same Framework.

In a dynamically extended OSGI environment, Framework manages the installation and update of components, as well as the dependencies between components and Services.

Framework provides the necessary resources for component developers to develop on the Java platform, provides the function of code dynamic loading for the developed components, and makes it easy for developers to develop and deploy a large-scale Services.

Second, Framework provides a concise and consistent programming model for Java component developers, simplifying the complexity of development and deployment. The programming model allows developers to bind their interface specifications to Service in the OSGI environment.

A consistent programming model helps developers cope with estimable critical errors. Framework will run on different hardware environments, but consistent interfaces ensure that components can run on consistent service interfaces.

2. Module layer

The module layer is the most basic part of the OSGi framework.

The modularization of OSGi defines which classes should be exposed and which classes should be hidden by adding metadata to the Jar package, and its control unit is called component Bundle (jar package).

Bundle is a modular physical unit in the form of a jar package, including code, resource files, and metadata (metadata), and the physical boundary of the jar package is also the encapsulation boundary of the runtime logic module.

Bundle is the basic component of OSGi, which is still represented by the traditional Jar package in the concept of Java.

It is further defined through the MANIFEST.MF file in the META-INF directory.

Typically, a MANIFEST.MF file contains the following contents:

Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-Name: Util Bundle-SymbolicName: com.ibm.director.la.util Bundle-Version: 1.0.0 Bundle-RequiredExecutionEnvironment: J2SE-1.5 Import-Package: org.osgi.framework;version= "1.3.0" Export-Package: com.ibm.director.la.util;uses:= "org.osgi.framework" Bundle-ClassPath: lib/junit.jar

The MANIFEST.MF file actually stores the metadata of Bundle.

The content of metadata can accurately define the various characteristics of Bundle, at the same time, it can better identify Bundle and help users understand Bundle.

3. Life cycle layer

The lifecycle layer belongs to the upper layer of the module layer in the OSGi framework, and the operation of the lifecycle layer is based on the functions of the module layer.

The main function of the lifecycle layer is to control the dynamic installation, opening, closing, updating, and uninstalling of components.

The lifecycle layer can manage applications externally or build applications that can manage themselves (or a combination of both), and give the application itself a lot of dynamics.

The use of Bundle requires the API of the lifecycle layer to interact with the lifecycle layer of the OSGi framework.

4. Service layer

The OSGi service is a Java object registered with the OSGi framework. You can set the properties of Service when you register. When you get the Service, you can filter based on the attribute.

Bundle can register Service or query Service through the context of Bundle.

Module layer 1. Brief introduction to Modularization

Modularization is to decompose a large-scale system into several smaller cooperative logic units, and to improve the maintainability and encapsulation of the system by forcing the logical boundaries between modules.

The module defines a logical boundary, and the module itself controls exactly which classes are completely encapsulated and which classes need to be exposed for external use. Developers can easily mask the implementation inside the module and expose the public API to the outside.

2. OSGI modularization and object-oriented

All functions are not crammed into the same class in object-oriented programming. Object-oriented programming discovers multiple things from the problem domain, each of which is responsible for different functions and tries to achieve high cohesion and low coupling. Object-oriented modular granularity is at the class level.

The modularity of OSGi defines which classes should be exposed and hidden in the package by adding metadata to the JAR package, and the granularity that controls visibility is at the component (JAR package) level.

The capabilities brought by OSGI modularization and object-oriented ideas are to ensure high cohesion and low coupling by controlling visibility and availability, but the granularity is different, one is at the component level, the other is at the object level.

3. The limitation of JAVA in modularization.

A. visibility control of the underlying code

Java provides four access control levels: private, public, protected and package private (without modifiers), providing the underlying OO data encapsulation features. Packege has the effect of splitting code, but if the code in the package is to be visible outside the package, it must be set to public (protected, using inheritance).

Org.serc.helloworld.Hello.java: defines an interface

Package org.serc.helloworld; public interface Hello {void sayHello ();}

Org.serc.helloworld.impl.HelloImpl.java: implements the Hello interface

Package org.serc.helloworld.impl;import org.serc.helloworld.Hello;public class HelloImpl implements Hello {final String helloString;public HelloImpl (String helloString) {this.helloString = helloString;} public void sayHello () {System.out.println (this.helloString);}}

Org.serc.helloworld.main.Main.java file:

Package org.serc.helloworld.main;import org.serc.helloworld.Hello;import org.serc.helloworld.HelloImpl;public class Main {final String helloString;public static void main (String [] args) {Hello hello = new HelloImpl ("Hello,SERC!"); hello.sayHello ();}

The three files are in different packages. The implementation details of HelloImpl should not be exposed to other packages, but it can be seen from the main method of Main.java that in order to create an instance of Hello, the HelloImpl class must be introduced, but HelloImpl, as the implementation detail of the interface, should not be exposed to consumers, violating the principle of encapsulation.

If you don't want to expose HelloImpl, you need to do extra work to make sure that you can hide the implementation details and simply create an instance that implements the Hello interface. This can be done in a variety of ways (such as factory mode), but adding extra work that has nothing to do with the functionality of the application itself is the limitation of Java.

B, limitations of classpath

When you add a jar package to classpath, only the file path is given, while the version, consistency, and dependencies of the jar package cannot be explicitly set in classpath or see the corresponding properties in classpath.

The jar package in classpath is loaded sequentially, for example:

Classpath=/servlet2.2/servlet.jar;/servlet2.3/servlet.jar, in practical application, Java uses servlet2.2 instead of servlet2.3. If teams develop separately in a large system, using different servlet packages and different version numbers, it is difficult to figure out which version of the servlet package is used when finally merging the development results.

Even if classpath can notice the problem with the version, it can't pinpoint the dependencies. The developer needs to increase the dependency package according to the prompt until the virtual machine does not run until the package is missing.

C, OSGI improve the limitation of JAVA

The limitations of JAVA are well addressed in OSGi:

Package visibility: by introducing the package visibility mechanism, OSGi can completely control which modules the code in a package is visible to, not just undifferentiated visibility, thus improving the code access control mechanism of Java.

Version of the package: by adding version information to the package, OSGi can precisely control the dependency of the code, ensure the version consistency of the code, and make up for the shortcomings of classpath.

4. Brief introduction of component Bundle

A bundle is a modular physical unit in the form of a jar package, which contains code, resource files, and metadata (metadata), and the physical boundary of the jar package is also the encapsulation boundary of the runtime logic module.

After adding some modular features (metadata) of components (bundle) to the manifest file of the standard jar package, the jar package becomes a bundle.

The biggest difference between bundle and normal jar packages is metadata.

The purpose of Bundle metadata is to accurately describe the bundle characteristics related to modularization, and to let the OSGi framework do all kinds of processing work on bundle (such as dependency parsing, mandatory encapsulation, etc.). There are three main parts of metadata:

A, readable information (optional)

The OSGi standard defines several metadata entries to help better understand and use bundle, but none of them are necessary and have no impact on modularity, and the OSGi framework completely ignores readable information.

Bundle-Name: SERC HelloworldBundle-Vendor: GR, SERCBundle-DocURL: http://elevenframework.orgBundle-Category: exampleBundle-Copyright: SERC

B, bundle identifier (required)

The bundle identifier is used to uniquely identify a bundle.

The early OSGi standard did not provide a way to identify a known bundle until the OSGi R4 standard, a "unique bundle identifier" was proposed. For backward compatibility, Bundle-Name cannot be used as an identifier, otherwise it will increase the work of maintaining backward compatibility, so the new manifest attribute Bundle-SymbolicName is used.

Bundle-SymbolicName: org.serc.helloworld

Bundle-Name is read to the user, while Bundle-SymbolicName is read to the OSGi framework, so that the OSGi framework can uniquely identify a bundle.

It is certainly possible to uniquely identify a bundle with only one Bundle-SymbolicName, but over time, there may be a new version of the bundle, and adding a version attribute will make the information of the bundle more accurate.

Bundle-Name: SERC HelloworldBundle-Vendor: GR, SERCBundle-DocURL: http://elevenframework.orgBundle-Category: exampleBundle-Copyright: SERC

C, code visibility (required)

Code visibility is used to define internal and external code. If the jar package in JavaSE is placed in classpath, then the jar package is visible to all programs under classpath, and the visibility cannot be changed. The OSGi standard defines the following attributes to describe the visibility of the code:

Bundle-ClassPath: defines the location of all the code that forms the bundle, the classpath in Java is the location of the defined jar package, and the Bundle-ClassPath attribute describes the path of the bundle inner class in the bundle. For example:

Bundle-ClassPath:.,other-classes/,embedded.jar

Export-Package: explicitly expose code that needs to be shared with other bundle, with each package separated by a comma, and each package can be modified with modifiers to other features of the package.

Export-Package: org.serc.hellworld; vendor= "SERC", org.serc.hellworld.impl; vendor= "Gou Rui"

Import-Package: define the external code that bundle depends on, in the same format as Export-Package, and you can also use modifiers to modify packages. Modifiers are used to limit the scope of dependent packages, similar to filters, rather than the characteristics used to declare packages in Export-Package. For example:

Import-Package: org.serc.helloworld; vendor= "SERC"

Life cycle layer 1. Brief introduction of life cycle layer

The life cycle layer belongs to the upper layer of the module layer in the OSGi framework, and its operation is based on the functions of the module layer. The main function of the lifecycle layer is to enable developers to manage applications externally or build applications that can manage themselves (or a combination of both), and to make the application itself very dynamic.

2. Brief introduction to Lifecycle Management

Generally speaking, a program (or part of a program) must obey some kind of life cycle. There are four typical phases in the life cycle of software, as follows:

If you are creating an application, you must first install (install) the application; when all the dependencies of the application are satisfied, you can execute the application; if the application is no longer needed, you can stop (stop); after a period of time, you may need to update (update) the version of the application; eventually, you may remove the application.

The lifecycle management process of the application is completed by operating the application externally or internally. For non-modular applications, the operation is targeted at the entire application; for modular applications, there can be more fine-grained lifecycle management (for a module in the application).

3. OSGi bundle life cycle

To use bundle, you have to use the API of the lifecycle layer to interact with the lifecycle layer of the OSGi framework.

The core of the OSGi framework does not force the use of any specific API interaction mechanism (such as command line, GUI, or XML configuration files, etc.), it is just a simple Java API, developers can create their own desired interaction patterns to ensure the flexibility of the framework.

In standard Java programming, jar packages are used by putting jar packages into classpath, whereas bundle is different. Bundle can only be used when it is installed (install) into a running instance of the OSGi framework, and the OSGi framework supports the complete life cycle management of bundle, and supports these management operations when the application is completed, which shows its dynamic nature.

The state transition diagram for the Bundle lifecycle is as follows:

The current state of the bundle can be obtained through the getState method of Bundle.

The Starting and Stopping states are transient and will automatically transfer to the next state after they last for a while without the need for a transition condition.

4. Lifecycle layer API

The API of the life cycle layer is mainly composed of three core interfaces: BundleActivator, BundleContext and Bundle.

A 、 BundleActivator

BundleActivator allows developers to capture bundle's start and stop events and make custom responses to them.

The APIs of BundleActivator are defined as follows:

Public interface BundleActivator {public void start (BundleContext context) throws Exception; public void stop (Bundlecontext context) throws Exception;}

If a class implements the BundleActivator interface, the class becomes an Activator. But it is not enough to have an implementation. Let the OSGi framework know that Activator exists. So you also need to add the following attribute to the MANIFEST file:

Bundle-Activator:org.demo.Activator

When bundle starts (start), the OSGi framework calls the start method of Activator, which also applies to the stop method.

Not every bundle needs an activator, and sometimes bundle is just to share code with other bundle, without having to make redundant actions when starting and stopping. Whether or not to use BundleActivator excuses requires a specific analysis of specific problems.

B 、 BundleContext

BundleContext is the execution-time context of bundle in the framework and provides a way to interact with the framework.

The methods in the BundleContext interface are mainly divided into two categories, one is related to deployment and lifecycle management, and the other is about using the service layer for inter-bundle interaction.

Public interface BundleContext {String getProperty (String key); Bundle getBundle (); Bundle installBundle (String location, InputStream input) throws BundleException; Bundle installBundle (String location) throws BundleException; Bundle getBundle (long id); Bundle [] getBundles (); void addBundleListener (BundleListener listener); void removeBundleListener (BundleListener listener); void addFrameworkListener (FrameworkListener listener); void removeFrameworkListener (FrameworkListener listener);}

The BundleContext interface is the only execution context for the bundle associated with it, and the context is meaningful only if the bundle belongs to the active state, that is, between the point in time when the start method is called and the stop method is called. If a bundle is not in the active period, but the component's bundlecontext object is used, the framework throws an exception.

Another purpose of the framework's use of this context object is for bundle security and resource allocation, so BundleContext objects should be treated as private objects and should not be passed between bundle at will.

C 、 Bundle

Bundle logically means that a physical bundle in a bundle,OSGi environment corresponds to a bundle object. The bundle object contains the basic information of bundle and the control interface of the bundle declaration cycle.

In the BundleContext interface, the getBundle method can get the Bundle object.

For each bundle installed into the framework, the framework creates a Bundle object to logically express it. The method of bundle lifecycle management is defined in the Bundle interface:

Public interface Bundle {BundleContext getBundleContext (); long getBundleId (); Dictionary getHeaders (); Dictionary getHeaders (String locale); String getLocation (); int getState (); String getSymbolicName (); Version getVersion (); void start (int options) throws BundleException; void start () throws BundleException; void stop (int options) throws BundleException; void stop () throws BundleException; void update (InputStream input) throws BundleException; void update () throws BundleException; void uninstall () throws BundleException;}

Most OSGi framework implementations interpret locatioin as a URL pointing to OSGi bundle, and download bundle to the framework through URL when needed to install and use it. However, the OSGi standard does not stipulate that the form of location must be URL, and URL is not a must, and bundle can be installed through the input stream (Input Stream).

Bundle cannot change its own state. For example, if a bundle of active cannot stop itself, stop will throw an exception.

5. Service layer 1. Service introduction

A service is a contract between a service provider and a service consumer. Consumers generally do not care about the details of the service implementation, but only care about whether the contract is satisfied (what function the service should provide and what format it should satisfy). The process of using the service includes the form of discovering the service and reaching an agreement, and the corresponding service needs to be found through the iconic characteristics of the service.

2. OSGI service layer

The service layer is the top layer in the OSGi framework. The service layer brings more dynamics and uses a service-oriented programming model. When a bundle discovers that it starts to use a service in OSGi, the service may change or disappear at any time.

The OSGi framework has a centralized registry that follows the publish-find-bind model:

A bundle that provides a service can publish POJO as an entity of the service; a bundle that uses the service can find and bind the service through the registry.

You can publish, discover and bind services through the BundleContext API, as shown below:

Public interface BundleContext {void addServiceListener (ServiceListener listener, String filter) throws InvalidSyntaxException; void addServiceListener (ServiceListener listener); void removeServiceListener (ServiceListener listener); ServiceRegistration registerService (String [] clazzes, Object service, Dictionary properties); ServiceRegistration registerService (String clazz, Object service, Dictionary properties); ServiceRegistration [] getServiceReferences (String clazz, String filter) throws InvalidSyntaxException; ServiceRegistration [] getAllServiceReferences (String clazz, String filter) throws InvalidSyntaxException; ServiceReference getServiceReference (String clazz); Object getService (ServiceReference reference) Boolean ungetService (ServiceReference reference);} 3. Publishing service

In order for other bundle to discover the service, the service must be described before it is published. Service characteristics include the name of the interface (which can be an array of names), the implementation of the interface, and metadata information of an optional java.util.Dictionary type. Examples are as follows:

String [] interfaces = new String [] {StockListing.class.getName (), StockChart.class.getname ()}; Dictionary metadata = new Properties (); metadata.setProperty ("name", "LSE"); metadata.setProperty ("currency", Currency.getInstance ("GBP"); metadata.setProperty ("country", "GB"); ServiceRegistration registration = bundleContext.registerService (interfaces, new LSE (), metadata)

In the above code, the metadata of the service can be updated through the ServiceRegistration object:

Registration.setProperties (newMetadata)

Services can be logged out directly:

Registration.unregister ()

The ServiceRegistration object cannot be shared with other Bundles because the life cycle of the ServiceRegistration object and the bundle that publishes the service are interdependent. If bundle no longer exists in the framework execution environment, then the ServiceRegistration object should not exist either.

The parameter new LSE () in the code is a POJO, and you don't need to implement any OSGi types or use annotations, as long as you meet the service contract.

If you bundle and stop before deleting the published service, the framework will help delete the service.

4. Discovery service

The correct service can be found in the registry according to the service contract. The interfaces that discover the service and get its reference are as follows:

ServiceReference reference = bundleContext.getServiceReference (StockListing.class.getName ())

Reference is an indirect reference to the service object. The purpose of not using the service object directly is to decouple the use of the service and the implementation of the service, and use the service registry as the middleman to track and control the service. At the same time, it can also notify the consumer after the service disappears.

ServiceReference can be shared between bundle regardless of the lifecycle of the bundle that uses the service.

In the getServiceReference method, the default priority for selecting service is the highest for service.rank first, and the earliest to register in the framework if the rank is equal. In addition to the default rules, you can do some filtering in getServiceReferences by adding a filter parameter (as the second parameter to call the method).

ServiceReference [] references = bundleContext.getServiceReferences (StockListing.class.getName (), "(& (currency=GBP) (objectClass=org.example.StockChart)")

The matching parameter is a string. The format of the string belongs to the LDAP query format and is fully described in the RFC1960 standard.

The content to the left of the equal sign in the string is the left value in the Dictionary, which is matched with the service's metadata by the right value corresponding to the left value. Examples of matches are as follows:

Property matching:

(name=John Smith) (age > = 20) (age

Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.

Views: 0

*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.

Share To

Internet Technology

Wechat

© 2024 shulou.com SLNews company. All rights reserved.

12
Report