0

特定の形式のファイルを読み取る OSGi でサービスを構築しようとしています。

サービス インターフェイスは次のようになります。

public interface FileReaderService {
    /**
     * Reads the given file.
     * @param filePath Path of the file to read
     * @return the data object built from the file
     * @throws IOException if there is an error while reading the file
     */
    Data readFile(Path filePath) throws IOException;

    /**
     * Detects if the format of the provided file is supported.
     * @param filePath the file to check
     * @return true if the format of the file is supported, false otherwise
     * @throws IOException if there is an error while reading the file
     */
    boolean isFormatSupported(Path filePath) throws IOException;
}

Data オブジェクトは、読み取るファイルのデータ構造を定義するクラスです (同じ種類のデータが含まれているはずです)。

アイデアは、次のようなさまざまなサービスの実装を持つことです。

public class TxtFileReader implements FileReaderService {

    @Override
    public Data readFile(Path filePath) throws IOException {
            // Do something smart with the file
            return data;
        }
    }

    @Override
    public boolean isFormatSupported(Path filePath) throws IOException {
        PathMatcher matcher = FileSystems.getDefault().getPathMatcher("glob:*.txt");
        return matcher.matches(filePath);
    }
}

XmlFileReader、MdFileReader など、他の実装もある可能性があります。

最後に、次のような FileReaderFactory が必要です。

@Component
public class FileReaderFactory implements FileReaderService {

    private List<FileReaderService> availableServices = new ArrayList<>();

    @Override
    public Data readFile(Path filePath) throws IOException {

        for (FileReaderService reader : availableServices) {
            if (reader.isFormatSupported(filePath)) {
                return reader.readFile(filePath);
            }
        }

        return null;
    }

    @Override
    public boolean isFormatSupported(Path filePath) throws IOException {
        for (FileReaderService reader : availableServices) {
            if (reader.isFormatSupported(filePath)) {
                return true;
            }
        }
        return false;
    }
}

私が望むのは、DS が FileReaderServices をファクトリ リストに動的に挿入することです。提供されるサービスの数に応じて、特定のファイル形式をサポートする (またはサポートしない) ことになります。

したがって、私の質問は次のとおりです。

1) これは DS で実行可能ですか?

2) はいの場合、DS 注釈を使用してそれを行うにはどうすればよいですか?

3) そうでない場合、どのようにしますか?

ありがとう

編集:クリスチャンの解決策を試しましたが、うまくいきませんでした(まだ)。完全なコードは、 https ://github.com/neopium/FileReader からダウンロードできます。

4

2 に答える 2

2

@Reference でリストに注釈を付けます。

@Reference(service = FileReaderService.class)
private List<FileReaderService> availableServices;

これを機能させるには、DS 1.3 が必要です。最新の felix scr バージョンはこれをサポートしています。

再帰が発生する可能性があるため、FileReaderFactory を FileReaderService としてエクスポートすることはお勧めしません。

于 2016-01-10T18:25:43.750 に答える
0

Christian Schneider が示したように、解決策は @Reference アノテーションを使用することでした。

ただし、彼の回答で指定されているように使用すると、Karaf がクラッシュしました。

Cannot register Component
org.osgi.service.component.ComponentException: Component org.test.reader.service.factory.FileReaderFactory validation failed: Field value type must not be set for unary field references.

Felix SCR ソース コードを調べると、クラス org.apache.felix.scr.impl.metadata.ReferenceMetadata で例外を引き起こしている行が見つかりました。

// field value type
if ( !m_isMultiple )
{
    // value type must not be specified for unary references
    if ( m_field_collection_type != null )
    {
        throw componentMetadata.validationFailure( "Field value type must not be set for unary field references." );
    }
}

カーディナリティが指定されていないのに、属性 m_field_collection_type がコンポーネント XML で「サービス」に設定されている (つまり、null でない) ため、Felix SCR は満足していないようです...

したがって、注釈を次のように変更しました。

@Reference(cardinality = ReferenceCardinality.AT_LEAST_ONE)
private List<FileReaderService> availableServices;

アプリケーションをテストするために、ファクトリ サービス コンシューマも追加しました。

興味のある方は、修正されたソース コードをこちらから入手できます: https://github.com/neopium/FileReader

于 2016-01-14T14:59:26.110 に答える