Pengenalan OSGi

1. Pengenalan

Beberapa aplikasi misi kritikal dan middleware Java mempunyai beberapa keperluan teknologi yang sukar.

Ada yang harus menyokong penggunaan panas, agar tidak mengganggu perkhidmatan yang sedang berjalan - dan yang lain harus dapat bekerja dengan versi lain dari pakej yang sama demi menyokong sistem warisan luaran.

The OSGi platform mewakili penyelesaian yang berdaya maju untuk menyokong ini jenis keperluan.

The Service Terbuka Gateway Initiative adalah spesifikasi mentakrifkan sistem komponen berasaskan Java. Ia kini dikendalikan oleh OSGi Alliance , dan versi pertamanya bermula pada tahun 1999.

Sejak itu, ia terbukti menjadi standard yang baik untuk sistem komponen, dan ia digunakan secara meluas pada masa kini. The Eclipse IDE , misalnya, adalah satu OSGi permohonan -Berdasarkan.

Dalam artikel ini, kami akan meneroka beberapa ciri asas OSGi yang memanfaatkan pelaksanaan yang disediakan oleh Apache .

2. Asas OSGi

Dalam OSGi, satu komponen disebut bundle.

Secara logiknya, bundle adalah fungsi yang mempunyai kitaran hidup bebas - yang bermaksud ia boleh dimulakan, dihentikan dan dikeluarkan secara bebas.

Secara teknikal, bundle hanyalah fail jar dengan fail MANIFEST.MF yang mengandungi beberapa header khusus OSGi.

The OSGi platform menyediakan cara untuk menerima pemberitahuan mengenai berkas menjadi ada atau apabila ia dikeluarkan dari platform. Ini akan membolehkan klien yang dirancang dengan betul untuk terus bekerja, mungkin dengan fungsi yang merosot, walaupun perkhidmatan yang bergantung kepadanya, tidak tersedia buat sementara waktu.

Oleh kerana itu, satu bundle harus menyatakan secara eksplisit pakej apa yang perlu diakses dan platform OSGi akan memulakannya hanya jika kebergantungan tersedia di bundle itu sendiri atau dalam bundle lain yang sudah dipasang di platform.

3. Mendapatkan Alat

Kami akan memulakan perjalanan kami di OSGi dengan memuat turun versi terbaru Apache Karaf dari pautan ini. Apache Karaf adalah platform yang menjalankan aplikasi berasaskan OSG ; ia berdasarkan Apache pelaksanaan 's OSGi spesifikasi dipanggil Apache Felix .

Karaf menawarkan beberapa ciri berguna di atas Felix yang akan membantu kami berkenalan dengan OSGi , misalnya, antara muka baris arahan yang akan membolehkan kami berinteraksi dengan platform.

Untuk memasang Karaf , anda boleh mengikuti arahan pemasangan dari dokumentasi rasmi.

4. Titik Masuk Bundle

Untuk melaksanakan aplikasi dalam lingkungan OSGi, kita harus mengemasnya sebagai bundle OSGi dan menentukan titik masuk aplikasi, dan itu bukan kaedah utama (String [] args) utama kekosongan awam biasa .

Oleh itu, mari kita mulakan dengan membina aplikasi "Hello World" berasaskan OSG .

Kami mula menetapkan kebergantungan sederhana pada API OSGi teras :

 org.osgi org.osgi.core 6.0.0 provided 

Ketergantungan dinyatakan sebagai disediakan kerana ia akan tersedia pada waktu operasi OSGi , dan paket tidak perlu membenamkannya.

Mari sekarang tulis kelas HelloWorld ringkas :

public class HelloWorld implements BundleActivator { public void start(BundleContext ctx) { System.out.println("Hello world."); } public void stop(BundleContext bundleContext) { System.out.println("Goodbye world."); } }

BundleActivator adalah antara muka yang disediakan oleh OSGi yang harus dilaksanakan oleh kelas yang merupakan titik masuk untuk kumpulan.

Kaedah mula () dipanggil oleh platform OSGi apabila kumpulan yang mengandungi kelas ini dimulakan. Sebaliknya stop () dipanggil sebelum sebelum bundle dihentikan.

Ingatlah bahawa setiap kumpulan boleh mengandungi paling banyak satu BundleActivator . The BundleContext objek yang diberikan kepada kedua-dua kaedah membolehkan berinteraksi dengan OSGi runtime. Kami akan membalasnya tidak lama lagi.

5. Membina Bundle

Mari ubah suai pom.xml dan jadikan ia sebagai kumpulan OSGi sebenar.

Pertama sekali, kita harus menyatakan secara jelas bahawa kita akan membina kumpulan, bukan balang:

bundle

Kemudian kami memanfaatkan plugin maven-bundle, dengan ihsan dari komuniti Apache Felix , untuk mengemas kelas HelloWorld sebagai bundle OSGi :

 org.apache.felix maven-bundle-plugin 3.3.0 true    ${pom.groupId}.${pom.artifactId}  ${pom.name} ${pom.version}  com.baeldung.osgi.sample.activator.HelloWorld   com.baeldung.osgi.sample.activator    

Di bahagian arahan, kami menentukan nilai header OSGi yang ingin kami sertakan dalam fail MANIFEST bundle.

Bundle-Activator adalah nama lengkap pelaksanaan BundleActivator yang akan digunakan untuk memulakan dan menghentikan kumpulan, dan ini merujuk kepada kelas yang baru saja kita tulis.

Private-Package bukan header OSGi, tetapi ia digunakan untuk memberitahu plugin untuk memasukkan paket dalam paket tetapi tidak membuatnya tersedia untuk yang lain. Kami kini boleh membina ikatan dengan arahan biasa MVN pemasangan bersih .

6. Memasang dan Menjalankan Bundle

Mari mulakan Karaf dengan melaksanakan perintah:

/bin/karaf start

di mana adalah folder tempat Karaf dipasang. Apabila arahan konsol Karaf muncul, kami dapat menjalankan perintah berikut untuk memasang bundle:

> bundle:install mvn:com.baeldung/osgi-intro-sample-activator/1.0-SNAPSHOT Bundle ID: 63

Ini memerintahkan Karaf untuk memuatkan paket dari repositori Maven tempatan.

In return Karaf prints out the numeric ID assigned to the bundle that depends on the number of bundles already installed and may vary. The bundle is now just installed, we can now start it with the following command:

> bundle:start 63 Hello World

“Hello World” immediately appears as soon the bundle is started. We can now stop and uninstall the bundle with:

> bundle:stop 63 > bundle:uninstall 63

“Goodbye World” appears on the console, accordingly to the code in the stop() method.

7. An OSGi Service

Let's go on writing a simple OSGi service, an interface that exposes a method for greeting people:

package com.baeldung.osgi.sample.service.definition; public interface Greeter { public String sayHiTo(String name); }

Let's write an implementation of it that is a BundleActivator too, so we'll be able to instantiate the service and register it on the platform when the bundle is started:

package com.baeldung.osgi.sample.service.implementation; public class GreeterImpl implements Greeter, BundleActivator { private ServiceReference reference; private ServiceRegistration registration; @Override public String sayHiTo(String name) { return "Hello " + name; } @Override public void start(BundleContext context) throws Exception { System.out.println("Registering service."); registration = context.registerService( Greeter.class, new GreeterImpl(), new Hashtable()); reference = registration .getReference(); } @Override public void stop(BundleContext context) throws Exception { System.out.println("Unregistering service."); registration.unregister(); } }

We use the BundleContext as a mean of requesting the OSGi platform to register a new instance of the service.

We should also provide the type of the service and a map of the possible configuration parameters, which aren't needed in our simple scenario. Let's now proceed with the configuration of the maven-bundle-plugin:

 org.apache.felix maven-bundle-plugin true    ${project.groupId}.${project.artifactId}   ${project.artifactId}   ${project.version}   com.baeldung.osgi.sample.service.implementation.GreeterImpl   com.baeldung.osgi.sample.service.implementation   com.baeldung.osgi.sample.service.definition    

It's worth noting that only the com.baeldung.osgi.sample.service.definition package has been exported this time, through the Export-Package header.

Thanks to this, OSGi will allow other bundles to invoke only the methods specified in the service interface. Package com.baeldung.osgi.sample.service.implementation is marked as private, so no other bundle will be able to access the members of the implementation directly.

8. An OSGi Client

Let's now write the client. It simply looks up the service at startup and invokes it:

public class Client implements BundleActivator, ServiceListener { }

Let's implement the BundleActivator start() method:

private BundleContext ctx; private ServiceReference serviceReference; public void start(BundleContext ctx) { this.ctx = ctx; try { ctx.addServiceListener( this, "(objectclass=" + Greeter.class.getName() + ")"); } catch (InvalidSyntaxException ise) { ise.printStackTrace(); } }

The addServiceListener() method allows the client to ask the platform to send notifications about the service that complies with the provided expression.

The expression uses a syntax similar to the LDAP's one, and in our case, we're requesting notifications about a Greeter service.

Let's go on to the callback method:

public void serviceChanged(ServiceEvent serviceEvent) { int type = serviceEvent.getType(); switch (type){ case(ServiceEvent.REGISTERED): System.out.println("Notification of service registered."); serviceReference = serviceEvent .getServiceReference(); Greeter service = (Greeter)(ctx.getService(serviceReference)); System.out.println( service.sayHiTo("John") ); break; case(ServiceEvent.UNREGISTERING): System.out.println("Notification of service unregistered."); ctx.ungetService(serviceEvent.getServiceReference()); break; default: break; } }

When some modification involving the Greeter service happens, the method is notified.

When the service is registered to the platform, we get a reference to it, we store it locally, and we then use it to acquire the service object and invoke it.

When the server is later unregistered, we use the previously stored reference to unget it, meaning that we tell the platform that we are not going to use it anymore.

We now just need to write the stop() method:

public void stop(BundleContext bundleContext) { if(serviceReference != null) { ctx.ungetService(serviceReference); } }

Here again, we unget the service to cover the case in which the client is stopped before the service is being stopped. Let's give a final look at the dependencies in the pom.xml:

 com.baeldung osgi-intro-sample-service 1.0-SNAPSHOT provided   org.osgi org.osgi.core 6.0.0 

9. Client and Service

Let's now install the client and service bundles in Karaf by doing:

> install mvn:com.baeldung/osgi-intro-sample-service/1.0-SNAPSHOT Bundle ID: 64 > install mvn:com.baeldung/osgi-intro-sample-client/1.0-SNAPSHOT Bundle ID: 65

Always keep in mind that the identifier numbers assigned to each bundle may vary.

Let's now start the client bundle:

> start 65

Therefore, nothing happens because the client is active and it's waiting for the service, that we can start with:

> start 64 Registering service. Service registered. Hello John

What happens is that as soon as the service's BundleActivator starts, the service is registered to the platform. That, in turn, notifies the client that the service it was waiting for is available.

Pelanggan kemudian mendapatkan rujukan ke perkhidmatan dan menggunakannya untuk memanggil pelaksanaan yang disampaikan melalui paket perkhidmatan.

10. Kesimpulannya

Dalam artikel ini, kami meneroka ciri-ciri penting OSGi dengan contoh langsung bahawa cukup untuk memahami potensi OSGi.

Kesimpulannya, setiap kali kita harus memastikan bahawa satu aplikasi mesti dikemas kini tanpa merugikan, OSGi dapat menjadi penyelesaian yang dapat dilaksanakan.

Kod untuk siaran ini boleh didapati di GitHub.