2013-07-19 7 views
5

Obecnie mam problemy z OSGI i zdecydowałem się na nieco nietypowy przypadek użycia OSGI. Chciałbym go użyć w aplikacji wiersza poleceń. Chcę metodę main(..), która pobiera niektóre flagi i argumenty, robi coś i zamyka się ponownie. Czego nie chcę, to uruchomić Apache Karaf (lub podobne) i uruchamiać polecenia w konsoli OSGI (może to jednak stać się opcjonalną funkcją).Jak napisać aplikację z wiersza poleceń OSGI

Dlaczego OSGI dla aplikacji z wiersza poleceń jest w pierwszej kolejności? Aplikacja ma korzystać z różnych wersji tej samej biblioteki (elasticsearch). I po prostu dlatego, że jest to zepsute.

Czy powinienem korzystać z usługi w pakiecie lub poza nim? Jak to zrobić? Jakie problemy mogą się pojawić?

+0

To interesujący problem, jeszcze trudniejszy, jeśli chcesz pozwolić pakietom na korzystanie z opcji wiersza polecenia _discoverable_ (co było naszym przypadkiem użycia).Niestety, nasze ostateczne rozwiązanie było raczej ciężkie, a ja nie miałem czasu, aby go wypuścić do czegoś, co jeszcze inni mogliby wykorzystać ... –

Odpowiedz

6

Istnieje bardzo prosty sposób pisania aplikacji wiersza poleceń podczas korzystania z bnd. BND posiada funkcję tworzenia wykonywalny słoik z poleceniem pakiet:

$ bnd run xyz.bnd 
.... whatever your app does 
$ bnd package xyz.bnd 
$ ls 
    xyz.jar xyz.bnd ..... 
$ java -jar xyz.jar ... 
.... whatever your app does 

pamiętać, że ten słój jest kompletny, zawiera wszystkie pakiety, ramy, wyrzutni i właściwości, aby go uruchomić. Nie ma żadnych zewnętrznych zależności.

Sztuką jest uzyskanie głównego wątku (w którym wywoływana jest główna statyczna). Jedyne, co musisz zrobić, to zarejestrować usługę Runnable z właściwością main.thread=true. Program uruchamiający wywoła funkcję run() w tej usłudze, a następnie zakończy działanie (możesz pozostać w biegu tak długo, jak chcesz).

Aby uzyskać argumenty wiersza poleceń, można uzyskać usługę Object za pomocą właściwości launcher.arguments. Ta właściwość będzie zawierała twoje argumenty polecenia. Albo to zrobić ze składnikiem DS:

@Component(immediate=true, property="main.thread=true") 
public class Main implements Runnable { 
    String[] args; 

    public void run(){ ... } 

    @Reference(target="(launcher.arguments=*)") 
    void setArgs(Object service, Map<String,Object> props) { 
     this.args = (String[]) props.get("launcher.arguments"); 
    } 
} 

Najlepszym sposobem na to jest z bndtools ponieważ ułatwia przetestować/debugowania kodu. Najprawdopodobniej będziesz wtedy używał plików bndrun.

P.S. W najnowszym bnd możesz użyć parametru Callable <Integer> zamiast Runnable. Wartość zwracana jest następnie kodem zakończenia procesu. To może jednak nie być jeszcze obecne w bndtools.

+0

Dziękuję za odpowiedź. To naprawdę brzmi naprawdę łatwo. Czy zdajesz sobie sprawę, czy komenda 'package' została ujawniona przez wtyczkę maven-bundle? – sfussenegger

+0

Co masz na myśli przez "Object.class"? To powinno być po prostu usunięte, co czyni regularnym seter, prawda? – sfussenegger

+0

Myślę, że powinien to być parametr Object. Niestety, nie możesz go po prostu usunąć, mimo że interesuje Cię tylko parametr mapy. –

1

Aby odpowiedzieć na moje własne pytanie (Q&A style): I obecnie uwierzyć byłoby najlepiej

  1. początku OSGI embedded (czysty)
  2. rozpocząć pojemnikiem
  3. pakiet eksport API (org.osgi.framework.system.packages.extra)
  4. zainstalować i rozpocznij wymagane pakiety
  5. consume services outside of OSGI
  6. zamknięcie pojemnika
  7. wyjście aplikacja

Po wszystkie zestawy są uruchamiane można bezpiecznie założyć, wymagane usługi są dostępne. Zapobiega to również przekazywaniu konfiguracji do OSGI, która w rzeczywistości jest tylko argumentem dla wywołania usługi.