0

フレームワークについて学ぶために、単純なOSGiデモアプリケーションを構築しています。別のバンドル内から、またはOSGiフレームワークが埋め込まれたアプリケーションからアクティブなバンドルを更新したい(Neil BartlettによるOSGiの埋め込み方法で説明されているように)。

私のアプリケーションはこれらのバンドルに分割されています(読みやすくするために、投稿の最後にコードを配置しました)。

  1. com.dc.sszostek.interfaces-メソッドdraw()を持つ単一のShapeインターフェースが含まれています
  2. com.dc.sszostek.implementations-このSymbolicNameには2つのバンドルがあり、それぞれがShapeインターフェイスを実装しています。printlnはLine、もう1つはSquareです。それらのマニフェストファイルは両方とも同じであり、バンドルは実装が異なるだけです。
  3. com.dc.sszostek.programs-Painterプログラムが含まれています。それはShapeインターフェースを使用してdraw()を作成します(私はOSGiサービスを使用しました-Lars Vogelによるチュートリアルを使用して作成しました)。
  4. com.dc.sszostek.xmpp-SmackAPIを使用して実装されたJabberクライアントが含まれ、ファイル転送を待機し、ファイルを受信したときにcom.dc.sszostek.implementationsバンドルを更新しようとします。

私の問題は、アプリケーションにさまざまな実装を送信すると、ファイルが書き込まれるのに、バンドルが更新されないことです。

bundle.update()呼び出されても例外はスローされませんが、プログラムは線(または最初に配置したバンドルによっては正方形)を描画し続けます。OSGiコンソールからバンドルを更新すると、バンドルは正しく置き換えられ、デモは別の形を描き始めます。

誰かが私が犯している間違いがどこにあるのか教えてもらえますか、または実際の例を教えてもらえますか?

前もって感謝します。


com.dc.sszostek.interfaces

MANIFEST.MF

    Manifest-Version: 1.0
    Bundle-ManifestVersion: 2
    Bundle-Name: Provider
    Bundle-SymbolicName: com.dc.sszostek.interfaces
    Bundle-Version: 1.0.0
    Export-Package: com.dc.sszostek.interfaces

Shape.java

    package com.dc.sszostek.interfaces;

    public interface Shape {
        void draw();
    }

com.dc.sszostek.implementations

MANIFEST.MF

    Manifest-Version: 1.0
    Bundle-ManifestVersion: 2
    Bundle-Name: Impl
    Bundle-SymbolicName: com.dc.sszostek.implementations
    Bundle-Version: 1.0.0
    Bundle-Activator: com.dc.sszostek.implementations.Activator
    Export-Package: com.dc.sszostek.implementations
    Import-Package: org.osgi.framework, com.dc.sszostek.interfaces

Activator.java

    package com.dc.sszostek.implementations;

    import org.osgi.framework.BundleActivator;
    import org.osgi.framework.BundleContext;
    import com.dc.sszostek.interfaces.Shape;

    public class Activator implements BundleActivator {

        public void start(BundleContext ctx) throws Exception {
            ctx.registerService(Shape.class.getName(), new Line(), null);
        }

        public void stop(BundleContext ctx) throws Exception {}
    }

Line.java

    package com.dc.sszostek.implementations;

    import com.dc.sszostek.interfaces.Shape;

    public class Line implements Shape {
        public void draw() {
            System.out.println("*********");
        }
    }

com.dc.sszostek.programs

MANIFEST.MF

    Manifest-Version: 1.0
    Bundle-ManifestVersion: 2
    Bundle-Name: Prog
    Bundle-SymbolicName: com.dc.sszostek.programs
    Bundle-Version: 1.0.0
    Bundle-Activator: com.dc.sszostek.programs.Activator
    Export-Package: com.dc.sszostek.programs
    Import-Package: org.osgi.framework, com.dc.sszostek.interfaces

Activator.java

    package com.dc.sszostek.programs;

    import org.osgi.framework.BundleActivator;
    import org.osgi.framework.BundleContext;
    import org.osgi.framework.ServiceReference;
    import com.dc.sszostek.interfaces.Shape;

    public class Activator implements BundleActivator {
        private MyThread thread;

        public void start(BundleContext ctx) throws Exception {
            ServiceReference ref = getServiceReference(ctx);
            thread = new MyThread((Shape)ctx.getService(ref));
            thread.start();
        }

        public void stop(BundleContext ctx) throws Exception {
            ServiceReference ref = getServiceReference(ctx);
            ctx.ungetService(ref);
            thread.stopThread();
        }

        private ServiceReference getServiceReference(BundleContext ctx) {
            ServiceReference ref = ctx.getServiceReference(Shape.class.getName());
            return ref;
        }

        public static class MyThread extends Thread {
            private volatile boolean active = true;
            private final Shape service;

            public MyThread(Shape service) {
                this.service = service;
            }

            public void run() {
                while (active) {
                    service.draw();
                    try {
                        Thread.sleep(5000);
                    } catch (Exception e) {
                        System.out.println("Thread interrupted: " + e.getMessage());
                    }
                }
            }

            public void stopThread() {
                active = false;
            }
        }
    }

com.dc.sszostek.programs

MANIFEST.MF

    Manifest-Version: 1.0
    Bundle-ManifestVersion: 2
    Bundle-Name: FileReceiver
    Bundle-SymbolicName: com.dc.sszostek.xmpp
    Bundle-Version: 1.0.0
    Bundle-Activator: com.dc.sszostek.xmpp.Activator
    Bundle-ClassPath: ., lib/smack-3.2.1.jar, lib/smackx-3.2.1.jar
    Import-Package: org.osgi.framework, javax.net, javax.security.auth.callback, javax.net.ssl, javax.security.sasl,
        javax.naming.directory, javax.naming

Activator.java

    package com.dc.sszostek.xmpp;

    import org.jivesoftware.smack.*;
    import org.jivesoftware.smackx.filetransfer.*;
    import org.osgi.framework.Bundle;
    import org.osgi.framework.BundleActivator;
    import org.osgi.framework.BundleContext;
    import org.osgi.framework.BundleException;

    import java.io.File;
    import java.io.IOException;

    public class Activator implements BundleActivator {
        private Connection connection;

        public void start(BundleContext bundleContext) throws Exception {
            final BundleContext ctx = bundleContext;

            try {
                connection = new XMPPConnection("JABBER_SERVER");
                connection.connect();
                connection.login("USER", "PASS");

                final FileTransferManager manager = new FileTransferManager(connection);
                FileTransferNegotiator.getInstanceFor(connection);
                FileTransferNegotiator.setServiceEnabled(connection, true);

                manager.addFileTransferListener(new FileTransferListener() {
                    public void fileTransferRequest(FileTransferRequest request) {
                        IncomingFileTransfer transfer = request.accept();

                        File file = new File("D:\\bundles\\" + transfer.getFileName());

                        try {
                            file.createNewFile();
                        } catch (IOException e) {
                            System.out.println(e.getMessage());
                        }

                        try {
                            transfer.recieveFile(file);
                        } catch (XMPPException e) {
                            System.out.println(e.getMessage());
                        }

                        Bundle bundle = ctx.getBundle(2); //com.dc.sszostek.implementations is bundle number 2
                        try {
                            bundle.update();
                        } catch (BundleException e) {
                            System.out.println(e.getMessage());
                        }
                    }
                });
            } catch (Exception e) {
                System.out.println(e.getMessage());
            }
        }

        public void stop(BundleContext bundleContext) throws Exception {
            connection.disconnect();
        }
    }

4

2 に答える 2

1

OSGiのアクティベーターから始めないでください。アクティベーターは、不幸なことに過去から残っています。アクティベーターはシングルトンであり(これは本当に悪いです!)、依存関係を自分で処理するように強制します。他のバンドルに依存しないため、非常に特殊な場合に役立つことがありますが。ただし、事実上すべての場合、宣言型サービスが最適です。

多くの人がOSGiを下から学びたいと思っていますが、アクティベーターを使用することは、フレッドフリントストーンの車で今日の道路を運転する方法を学ぶようなものです。自分を傷つけるためにバインドされています。

あなたは実際にあなたがアクティベーターを使うときにあなたに起こるすべての落とし穴を示しています。アクティベーターを起動したときにサービスが存在することは保証されません。また、アクティベーターで外部サービスへの接続を開くという、非常に悪い考えを示しています。アクティベーターの開始/停止メソッドは、すべてのバンドルをすばやく開始するために非常に迅速である必要があります。

とにかく、ニールの提案を除いて。update()が指定した古いURLを使用していることに気づきましたか?URLが指すファイルを変更しましたか?update(InputStream)メソッドを使用して、バンドルが実際に更新されていることを確認することをお勧めします。

于 2013-02-26T11:24:35.320 に答える
0

実行中にサービスの実装が変更されると思いMyThreadますか?スレッドを開始する前に、サービスを1回だけ取得し、永久に再利用しているように見えるためです。これらの条件下では、少なくともスレッドを強制終了して再起動するまで、実装を変更することはできません。

于 2013-02-25T16:52:41.983 に答える