Ostatnia aktualizacja: 18/06/2026

Implementacja wtyczki

Wtyczka jest bundlem OSGi instalowanym w środowisku OSGi. Może być ona dynamicznie:

 

Wtyczka posiada własny kontekst, który pełni rolę kontenera komponentów wtyczki, serwisów, kontrolerów. Możliwe jest wstrzykiwanie zależności i korzystanie z możliwości SpringFramework.

 

Zobacz również: Implementacja modułów >

 

Deskryptor wtyczki

Deskryptor wtyczki to plik XML który dostarcza podstawowe informacje o wtyczce oraz jest miejscem na deklaracje wykorzystywanych modułów. Plik ten jest wymagany, ponieważ dostarcza informacje o wtyczce (jej unikalny identyfikator i wyświetlaną nazwę).

Deskryptor ma następującą strukturę:

<?xml version="1.0" encoding="UTF-8"?>
<plugin key="com.suncode.plugin-tutorial" name="Tutorial Plugin">
    <plugin-details>
        <description>
            <localized language="en">Description</localized>
            <localized language="pl">Opis</localized>
        </description>
        <author>Suncode</author>
        <requirements>
            <plusworkflow>3.2.200, 4.1.120, 4.2.8</plusworkflow>
            <com.suncode.plugin-dbexplorer>2.0.24</com.suncode.plugin-dbexplorer>
            <com.suncode.plugin-pwe>2.3.63</com.suncode.plugin-pwe>
        </requirements>
        <free-license>XXXXXXXXXXXXXXXXXXXXX</free-license>
        <changelog>https://docs.plusworkflow.pl/confluence/display/UNICMP/Change+Log+cuf-components</changelog>
        <documentation>https://docs.plusworkflow.pl/confluence/display/UNICMP/Cuf-components</documentation>
    </plugin-details>

    <!-- Wszystkie kolejne elementy stanowią deklaracje modułów -->
</plugin>

 

Element Opis
requirements Pozwala na określenie wymaganych zależności wtyczka. Zależność systemowa plusworfklow powinna być zgodna co do wersji z wersją parenta określoną w pom.xml.
free-license Pozwala na przypisanie wtyczce darmowej licencji — wtyczki posiadające ten wpis będą instalowały się jako "Darmowe" Wtyczki bez tej sekcji są płatne. Licencje są powiązane z identyfikatorem wtyczki
changelog Pozwala na wskazanie URLa do changeloga danej wtyczki. Link będzie dostępny do kliknięcia z poziomu centrum aktualizacji. Uwaga: link powinien wskazywać na zasoby publiczne, dostępne bez konieczności logowania.
documentation Pozwala na wskazanie URL z dokumentacją wtyczki. Link będzie dostępny z poziomu centrum aktualizacji.

 

Wtyczka może także zdefiniować PluginHook, jeżeli potrzebne jest wywołanie akcji przy starcie i zatrzymaniu wtyczki:

<?xml version="1.0" encoding="UTF-8"?>
<plugin key="com.suncode.plugin-tutorial" name="Tutorial Plugin" hook="com.suncode.plugin.tutorial.Hook">
    <!-- ... -->
</plugin>

 

Wymagania wtyczek

Wtyczka może zdefiniować swoje wymagania, które są sprawdzane podczas:

 

Wymagania są dzielone na:

 

Plik suncode-plugin.xml musi znajdować się w głównym katalogu pliku jar.

<?xml version="1.0" encoding="UTF-8"?>
<plugin key="com.suncode.plugin-tutorial" name="Tutorial Plugin">
    <plugin-details>
        <requirements>
            <!-- Wymaganie 'mandatory' na system PlusWorkflow -->
            <plusworkflow>3.2.50</plusworkflow>
            <!-- Wymaganie 'optional' na wtyczke o kluczu "com.suncode.plugin.pluginX" -->
            <com.suncode.plugin.pluginX optional="true">1.1</com.suncode.plugin.pluginX>
        </requirements>
    </plugin-details>
</plugin>

 

Operacje na wtyczkach

Ten rozdział pokazuje, jak korzystać z API mechanizmu wtyczek. Zarządzanie wtyczkami z poziomu systemu, znajduje się w zakładce Wtyczki.

 

Głównym komponentem mechanizmu wtyczek jest PluginFramework. W systemie PlusWorkflow należy pobrać ten obiekt z kontekstu aplikacji:

@Component
public class SomeComponent {
    @Autowired
    private PluginFramework framework; 
  
    /**
...
    */
}

 

import com.suncode.plugin.framework.PluginFramework;
import com.suncode.pwfl.util.SpringContext;
  
public class SomeClass {
    public static void doSomething(){
        PluginFramework framework = SpringContext.getBean( PluginFramework.class );
    /**
    ...
*/
}
}

 

// pobrany w dowolny sposób
// PluginFramework framework = ...
  
// 1. Instalacja wtyczki z podanego pliku
File pluginFile = new File("/fakepath");
Plugin plugin = framework.installPlugin( pluginFile );
  
// 2. Aktualizacja wtyczki
File updatedPluginFile = new File("/fakepath");
plugin.update( updatedPluginFile );
  
// 3. Uruchomienie wtyczki
plugin.start();
plugin.getState(); // PluginState.ACTIVE
  
// 4. Pobranie tłumaczenia
// zwraca "message1" jeżeli moduł I18N nie jest obecny, w przeciwnym wypadku zwraca znalezione tłumaczenie
plugin.getMessage("message1");
  
// 5. Zatrzymanie wtyczki
plugin.stop();
plugin.getState(); // PluginState.STOPPED

 


Konfiguracja kontekstu wtyczki

Każda wtyczka ma własny kontekst aplikacji (ApplicationContext), w którym rejestrowane są jej komponenty, kontrolery, importowane serwisy etc. Dzięki temu wtyczka może być pisana tak jak każda inna aplikacja wykorzystująca SpringFramework.

Kontekst może być konfigurowany na 2 sposoby:

 

Konfiguracja XML

Jeżeli wtyczka zawiera plik /META-INF/spring/plugin-context.xml, to na jego podstawie tworzony jest XmlOsgiPluginContext.

Jeżeli projekt buduje Maven, plik powinien znajdować się w src/main/resources/META-INF/spring/plugin-context.xml

Plik konfiguracji jest standardowym plikiem konfiguracji kontekstu aplikacji springframework i może wyglądać następująco:

 

plugin-context.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:tx="http://www.springframework.org/schema/tx"
    xsi:schemaLocation="http://www.springframework.org/schema/beans 
                        http://www.springframework.org/schema/beans/spring-beans.xsd
                        http://www.springframework.org/schema/tx 
                        http://www.springframework.org/schema/tx/spring-tx-3.2.xsd
                        http://www.springframework.org/schema/context 
                        http://www.springframework.org/schema/context/spring-context-3.2.xsd">
    <!-- Włączenie skanowania wtyczki w poszukiwaniu @Component -->
    <context:component-scan base-package="com.suncode.plugin.tutorial" />
</beans>

 

Konfiguracja Java

Od SpringFramework 3 możliwa jest konfiguracja kontekstu aplikacji w całości używając klas Java oznaczonych adnotacją @Configuration.

Jeżeli mechanizm wtyczek nie znajdzie pliku /META-INF/spring/plugin-context.xml to stworzy domyślny kontekst aplikacji, który skanuje całą wtyczkę w poszukiwaniu klas @Component (a więc również @Configuration).

 

Przykładowa konfiguracja (rejestruje tylko 1 bean klasy String):

package com.suncode.plugin.tutorial;
 
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
 
@Configuration
public class Config {
    @Bean
    public String someString() {
        return "asd";
    }
}

 


Import i udostępnianie serwisów

Wtyczki mają możliwość korzystania z serwisów (komponentów) systemowych lub z innych wtyczek. Mogą również udostępniać swoje serwisy innym zainstalowanym wtyczkom.

 

Import serwisów

Praktycznie każda wtyczka musi mieć dostęp do serwisów/komponentów PlusWorkflow. Wszystkie działania na użytkownikach, procesach wymagają odpowiednich serwisów. System Plus Workflow udostępnia mechanizmowi wtyczek wszystkie serwisy obecne w kontekście aplikacji.

Import tych powinien odbywać się poprzez moduł component-import.

<!-- Import serwisu UserService -->
<component-import key="userService" source="system" interface="com.suncode.pwfl.administration.user.UserService" />

 

Taka instrukcja spowoduje dodanie do kontekstu wtyczki wrappera tego serwisu.

Aby wykorzystać ten serwis, należy pobrać go z kontekstu wtyczki wykorzystując np. wstrzykiwanie zależności (@Autowired)

import com.suncode.pwfl.administration.user.UserService;
  
@Component
public class ServiceConsumer {
  
    @Autowired
    private UserService userService;
  
    public void printUserInfo(){
         
        User user = userService.get('admin');
        System.out.println("User 'admin' full name is: " + user.getFullName());
    }
}

 

Import serwisów z innych wtyczek wygląda podobnie:

<!-- Import serwisu MessageService -->
<component-import key="messageService" source="plugin" interface="com.suncode.plugin.test.MessageService" />

 

Udostępnianie serwisów

Wtyczki, które pozwalają na integracje lub udostępniają pewną specyficzną funkcjonalność, powinny udostępnić swoje serwisy innym wtyczką.

Udostępnianie serwisów często jest jedyną możliwością na przykład ze względu na transakcyjność i dostęp do skonfigurowanej bazy danych.

 

Wtyczka może udostępnić każdy swój komponent z kontekstu wtyczki. W tym celu komponent ten musi zostać oznaczony adnotacją Provides

import com.suncode.plugin.test.TestService;
  
@Service
@Provides(TestService.class)
public class TestServiceImpl implements TestService {
    /**
    ...
    */
}

 

Po uruchomieniu wtyczki podany serwis (w rezultacie jego instancja) zostanie zarejestrowana w ServiceRegistry pod kluczem com.suncode.plugin.test.TestService. 

Ze względu na to, że pod podaną nazwą klasy może być zarejestrowane wiele serwisów, możemy sprecyzować właściwości serwisu, aby konsument mógł pobrać ten właściwy używając filtrów.

@Provides(value = DashboardService.class, properties = { @ServiceProperty(name = "language", value = "pl") })

 

Każdy udostępniony serwis (poprzez adnotację @Provides) rejestrowany jest z właściwością plugin zawierającą klucz wtyczki, która zarejestrowała ten serwis. Dzięki temu utworzyć odpowiedni filtr aby, na przykład pobrać serwis z konkretnej wtyczki:

<component-import key="someService" source="plugin" interface="com.suncode.smth.Service" 
filter="(plugin=com.suncode.plugin-test)" />

 


Tworzenie widoków Freemaker

Wtyczki systemu Plus Workflow mogą serwować dynamiczne strony http zbudowane przy pomocy biblioteki FreemarkerNa tej stronie zostaną przedstawione podstawy tworzenia takich widoków.

 

Edytor Freemarker
Środowisko Eclipse nie posiada wbudowanego edytora Freemarker. Edytor taki może być zainstalowany osobno wraz z JBoss Tools. Więcej na: http://freemarker.org/editors.html

Freemarker jest alternatywą dla JSP, które nie może zostać zintegrowane w mechanizm wtyczek z wielu powodów. Szablony Freemarker są tworzone dynamicznie i nie wymagają kompilacji do klas Java.

Strony tworzone są dynamicznie poprzez wstawianie wartości obiektów z modelu prosto do szablonu. Model jest uzupełniany np. atrybutami żądania (HttpServletRequest) tak jak w przypadku JSP.

 

Uzupełnienie modelu odbywa się zazwyczaj w kontrolerze:

@Controller
public class HelloController {
  
    // Wynik tych 2 metod będzie taki sam
  
    @RequestMapping("/hello")
    public String sayHello(Model model){
        model.addAttribute( "username", "World" );
        return "hello"; // /views/hello.ftl
    }
  
    @RequestMapping("/hello2")
    public String sayHello(HttpServletRequest request){
        request.setAttribute( "username", "World" );
        return "hello"; // /views/hello.ftl
    }
}

 

Szablon:

<h1>Hello ${username}</h1>

 

Wynik:

<h1>Hello World</h1>

 

Freemarker obsługuje pętle, wyrażenia if..else, escape'owanie html, formatowanie dat etc. Zalecane jest zapoznanie się z dokumentacją http://freemarker.org/docs/index.html

Obiekt PluginRequestContext

Każdy renderowany widok .ftl ma dostęp do pomocniczego obiektu PluginRequestContext, który ułatwia pobieranie tłumaczeń, ścieżek etc:

<!-- Pobranie ścieżki kontekstowej wtyczki: /{contextPath}/plugin/{id}/  -->
${pluginContext.pluginContextPath}

<!-- Pobranie adresu relatywnego do kontekstu wtyczki: /{contextPath}/plugin/{id}/hello  -->
${pluginContext.getPluginContextUrl('hello')}
  
<!-- Pobranie ścieżki zasobów wtyczki: /{contextPath}/plugin/{id}/resources/{timestamp}  -->
${pluginContext.pluginResourcesPath}
 
<!-- Pobranie ścieżki do zasobu wtyczki: /{contextPath}/plugin/{id}/resources/{timestamp}/hello.js  -->
${pluginContext.getPluginResourcesUrl('hello.js')}
  
<!-- Pobranie contextPath: np. /PlusWorkflow -->
${pluginContext.contextPath}
  
<!-- Pobranie contextPath: np. /PlusWorkflow/Admin.do -->
${pluginContext.getContextUrl('Admin.do')}
  
<!-- Pobranie tłumaczenia klucza bez parametrów -->
${pluginContext.getMessage('messagekey')}
 
<!-- Pobranie tłumaczenia z parametrami -->
${pluginContext.getMessage('messagekey', ['somearg'])}

 

Makro plugin.ftl

Wtyczka może zaimportować makro, które upraszcza operacje na obiektie PluginRequestContext.

<!-- Import makra -->
<#import "/plugin.ftl" as plugin/>
  
<!-- Pobranie adresu relatywnego do kontekstu wtyczki: /{contextPath}/plugin/{id}/hello  -->
<@plugin.url 'hello'/>
  
<!-- Pobranie ścieżki do zasobu wtyczki: /{contextPath}/plugin/{id}/resources/{timestamp}/hello.js  -->
<@plugin.resourceUrl 'hello.js'/>
  
<!-- Pobranie contextPath: np. /PlusWorkflow/Admin.do -->
<@plugin.systemUrl 'Admin.do'/>
  
<!-- Pobranie tłumaczenia klucza bez parametrów -->
<@plugin.message 'messagekey'/>

 

Wykorzystanie JspTagLib

Freemarker umożliwia wywołania JspTagLib (np. displaytag, jstl).

Nie zaleca się wykorzystywania JspTagLib, lepszą alternatywą jest wykorzystanie komponentów JavaScript przeniesienie logiki do kontrolera.

jstl

<!-- Przypisanie do zmiennej "c" tagliba "JSTL" -->
<#assign c=JspTaglibs["http://java.sun.com/jsp/jstl/core"] />
  
<!-- <c:import...> -->
<@c.import charEncoding="UTF-8" url=someUrl />

 

displaytag

<!-- Przypisanie do zmiennej "display" tagliba "displaytag" -->
<#assign display=JspTaglibs["http://displaytag.sf.net"] />
  
<@display.table id="table" name="records" pagesize=20 partialList=true requestURI="someUrl">
    <@display.column title=pluginContext.getMessage("Lp") class="small">${table_rowNum}</@display.column>
    <!-- ... -->
</@display.table>

 

Dekoratory widoków

Widoki Freemarker generowane przez wtyczkę są domyślnie dekorowane tak, aby odpowiadały stylowi systemu Plus Workflow.

Domyślnie dekorowane są wszystkie żądania które:

W systemie dostępne są następujące dekoratory (nazwę używamy jako wartość parametru decorator):

Nazwa Opis URL
system Domyślny dekorator - wpisuje zawartość szablonu do obszaru body strony. Automatycznie wygenerowane zostanie nagłówek, menu systemowe, stopka. http://<serwer>:<port>/<system>/plugin/<wtyczka>/view?decorator=system
empty Pusty dekorator - zawiera wszystkie skrypty oraz style css. Nie zawiera żadnej struktury takiej jak header czy footer. http://<serwer>:<port>/<system>/plugin/<wtyczka>/view?decorator=empty
plain Prosty dekorator - zawiera tylko standardowe skrypty JavaScript http://<serwer>:<port>/<system>/plugin/<wtyczka>/view?decorator=plain
none Brak dekoratora. Wyświetlona zostanie tylko zawartość szablonu. http://<serwer>:<port>/<system>/plugin/<wtyczka>/view?decorator=none
notlogged Dekorator strony logowania do wyświetlania informacji o nieprawidłowym logowaniu http://<serwer>:<port>/<system>/plugin/<wtyczka>/view?decorator=notlogged

 


Mechanizm wtyczek

Biblioteka PluginFramework dostarcza system wtyczek, które mogą dowolnie zwiększać funkcjonalność systemu, w którym zostaną zainstalowane. Architektura modułów pozwala w sposób deklaratywny na dostarczanie dowolnej funkcjonalności (na przykład wsparcie dla Spring MVC) dla wtyczki.

 

Mechanizm wtyczek opiera się na OSGi. Dzięki czemu wtyczki mogą być dynamicznie uruchamiane i aktualizowane oraz korzystanie z różnych wersji bibliotek.

 

Konfiguracja mechanizmu wtyczki

Cała wymagana konfiguracja mechanizmu wtyczek musi znajdować się w pliku suncode-plugins.xml (w classpath).

Plik suncode-plugins.xml zawiera przede wszystkim konfigurację związaną z OSGi i widocznością klas systemowych we wtyczkach.

 

Przykładowa konfiguracja:

<?xml version='1.0' encoding='utf-8'?>
<suncode-plugins >
    <home-directory>../plugins</home-directory>
    <osgi strict-export="true">
        <bootdelegation>
            <!-- Core libs -->
            <package>org.springframework.*</package>
            <package>org.hibernate.*</package>
            <!-- Proxy - wymagane jeżeli wykorzystujemy spring i hibernate-->
            <package>javassist.*</package>
            <package>org.aopalliance.*</package>
        </bootdelegation>
        <export>
            <package version="1.4.0">org.apache.commons.io</package>
            <package version="1.4.0">org.apache.commons.io.filefilter</package>
        </export>
        <exported-packages>
            <pattern>com.**</pattern>
            <pattern>org.**</pattern>
            <pattern>net.**</pattern>
            <pattern>javax.**</pattern>
        </exported-packages>
        <excluded-packages>
        </excluded-packages>
    </osgi>
</suncode-plugins>

 

Opis poszczególnych sekcji pliku konfiguracyjnego:

Nazwa Opis Wymagany
home-directory

Wskazuje katalog domowy mechanizmu wtyczek. W tym katalogu zapisywane będą wtyczki i inne wymagane ustawienia.

Ścieżka może być absolutna, bądź relatywna do serwera.

Mechanizm wtyczek nie korzysta z bazy danych. Wszystkie wymagane dane trzymane są w podanym katalogu. Usunięcie katalogu usunie wszystkie zainstalowane wtyczki.

strict-export

Definiuje, czy wersje eksportowanych pakietów mają pochodzić z manifestu w przypadku bundli OSGi.

Flaga na wypadek problemów z kompatybilnością. Domyślnie true.

 
bootdelegation

Ustawienie OSGi. Wskazuje, jakie klasy powinny być zawsze ładowanie z classloadera, który załadował ten mechanizm wtyczek.

Ustawienie bootdelegation zawsze zawiera wpis com.suncode.plugin.framework.* - ładowanie wszystkich klas mechanizmu wtyczek z systemowego classloadera.

Ustawienie tej właściwości konieczne jest w przypadku gdy wtyczki wykorzystują np. proxy - sekcja ImportPackages nie zawiera takiego pakietu i klasa nie zostanie znaleziona. Można uniknąć tego problemu ustawiając bootdelegation bądź dodając odpowiednie wpisy w MANIFEST.MF

 

VisualVM Profiler

Jeżeli podczas używania Profilera VisualVM do profilowania wtyczek występują wyjątki ClassNotFoundException, to do bootdelegation należy dodać wpis:

org.netbeans.lib.profiler.*
 
export Lista pakietów eksportowanych z systemu bez względu czy występują one w classpath czy też nie. Konfiguracja używana może być np. aby zdefiniować inną wersję eksportowanego pakietu.  
exported-packages

Lista wzorców (w stylu ant) pakietów, które mają zostać wyeksportowane do środowiska OSGi. Skanowane są wszystkie pliki jar i katalogi w classpath. Dzięki temu, wtyczki mogą korzystać z klas głównego systemu.

Wzorce są wyrażeniami w stylu ant:

  •  
  • com.** → wszystkie pakiety zaczynające się od com.
  • com.suncode.* → wszystkie pod-pakiety (tylko 1 poziom) w pakiecie com.suncode
  • com.suncode.pwfl → tylko pakiet com.suncode.pwfl
W OSGi pakiety są także identyfikowane przez wersję. Dlatego exporter próbuje ustalić wersję pakietu, odczytując nazwę pliku jar lub informacje w MANIFEST.MF bądź w plikach tworzonych przez Maven'a.
Jeżeli klasy nie są zawarte w pliku jar, nie ma możliwości odczytania wersji pakietu. W takim wypadku przyporządkowywana jest im wersja 0.0.0
 
excluded-packages Lista wzorców (w stylu ant — tak jak w exported-packages) pakietów, które mają zostać wykluczone z eksportu do środowiska OSGi.  

 

Pierwsze uruchomienie mechanizmu wtyczek wiąże się ze stworzeniem katalogu domowego oraz skanem całego classpath w poszukiwaniu pakietów/klas spełniających podane wymagania. Jest to proces bardzo czasochłonny (nawet kilka minut - w zależności od maszyny).

Po pierwszym uruchomieniu tworzony jest cache pakietów, co przyśpiesza kolejne uruchomienia.

 


PluginFramework API

Uzupełnieniem tej dokumentacji jest JavaDoc.

Plugin API wykorzystywane jest do zarządzania pojedynczą wtyczką.

 

Obiekt (com.suncode.plugin.framework.Plugin) reprezentuje wtyczkę i umożliwia sterowanie jej stanem oraz komunikację z mechanizmem wtyczek. Obiekt ten można otrzymać poprzez:

// dowolny komponent (wewnątrz wtyczki lub w systemie)
@Component
public class SomeComponent {
  
    @Autowired
    private PluginFramework framework;
  
    public void method(){
        Plugin plugin = framework.getPlugin("plugin-key");
    }
}

 

// komponent wewnątrz wtyczki
@Component
public class SomePluginComponent {
  
    @Autowired
    private Plugin plugin;
  
    public void method(){
        plugin.getKey(); // klucz tej wtyczki
    }
}

 

Konieczne jest jednoznaczne wyszczególnienie wszystkich pakietów wykorzystywanych przez wtyczkę. Aby uprościć ten proces, większość pracy może zostać wykonana automatycznie przez wtyczkę maven-bundle-plugin.

W sytuacji, gdy nazwa klasy zostanie podana w statycznym zasobie, takim jak suncode-plugin.xml, wtyczka nie jest w stanie samodzielnie uzyskać tych informacji. W takich przypadkach wymagane jest dodatkowe skonfigurowanie wtyczki w pliku pom.xml.

<build>
<plugins>
    <plugin>
        <groupId>org.apache.felix</groupId>
        <artifactId>maven-bundle-plugin</artifactId>
        <configuration>
            <instructions>
                <!-- Importuj wszystkie pakiety wykorzystane w klasach oraz pakiet
                "com.suncode.plugin.tutorial"-->
                <Import-Package>*,com.suncode.plugin.tutorial</Import-Package>
            </instructions>
        </configuration>
    </plugin>
</plugins>
</build>

 

Cykl życia wtyczki

Wtyczka może być dynamicznie uruchamiana, zatrzymywana aktualizowana poprzez wywołanie odpowiednich metod na obiekcie tej wtyczki:

 

Uruchomienie wtyczki:

Plugin plugin = ...
  
plugin.start();
System.out.println(plugin.getState()); // wypisuje ACTIVE

 

Zatrzymanie wtyczki:

Plugin plugin = ...
 
plugin.stop();
System.out.println(plugin.getState()); // wypisuje STOPPED

 

Aktualizacja wtyczki z podanego pliku:

Plugin plugin = ...
 
plugin.update(new File("ścieżka do pliku jar wtyczki"));

 

Odinstalowanie wtyczki:

Odinstalowana wtyczka nie może być już wykorzystywana. Wywołanie jakiejkolwiek metody (z wyjątkiem kilku np. getState) zakończy się błędem.
Plugin plugin = ...
 
plugin.uninstall();
System.out.println(plugin.getState()); // wypisuje UNINSTALLED

 

Zasoby wtyczki

Każda wtyczka zbudowana jest z klas Java oraz statycznych zasobów.

Ze względu na izolację wtyczek, odczyt zasobów może odbywać się tylko z wykorzystaniem przedstawionych metod.

 

Pobieranie pojedynczych zasobów:

Plugin plugin = ...
  
Resource resource = plugin.getResource("suncode-plugin.xml"); // deskryptor wtyczki
if(resource.exists()){
    // zasób istnieje i można go odczytać
}

 

Wyszukiwanie zasobów:

Plugin plugin = ...
PluginContext context = plugin.getPluginContext();
  
// mappings/a.xml
// mappings/b.xml
// mappings/c.json
// mappings/sub/a.json
// mappings/sub/b.xml
  
// wszystkie pliki z katalogu mappings i podkatalogów
Resource[] resources = context.getResources( "mappings/**/*" );
// resources ma:
// mappings/a.xml
// mappings/b.xml
// mappings/c.json
// mappings/sub/a.json
// mappings/sub/b.xml
  
// wszystkie pliki xml z katalogu mappings
Resource[] resources = context.getResources( "mappings/*.xml" );
// resources ma:
// mappings/a.xml
// mappings/b.xml

 

Wzorzec zasobów jest wyrażeniem Ant. Więcej info w dokumentacji Springa PathMatchingPatternResolver.

 

Lokalne repozytorium

PluginStore dostępny jest od wersji 1.0.5 mechanizmu wtyczek — PlusWorkflow 3.1.7

 

PluginStore pozwala na zapisywanie zasobów (np. plików) w lokalnym repozytorium wtyczki.

Pliki zapisane w takim repozytorium są stałe tzn. nie są usuwane podczas zatrzymywania wtyczki. Stanowi to alternatywę dla baz danych.

 

Domyślna implementacja PluginStore przechowuje pliki w systemie plików w katalogu: <plugin-framework-home>/data/<plugin-key>.

 

Nie należy bazować na tej informacji podczas tworzenia wtyczek.

Pobieranie instancji store:

// z instancji wtyczki
PluginStore store = plugin.getPluginStore();
  
// poprzez @Autowired
@Autowired
private PluginStore store;

 

Komponent PluginStore może być pobrany zarówno z instancji wtyczki jak i z kontekstu tej wtyczki.

 

Zapis zasobów:

PluginStore store = ...
  
// zapis InputStream
PluginStoreResource resource = store.store("some/path/file.xml", inputStream);
resource.getPath(); // some/path/file.xml
resource.getInputStream();

 

Domyślne metody nie pozwalają na nadpisywanie plików. Aby nadpisywać pliki należy wykorzystać inny wariant metody.

Odczyt zasobów:

PluginStore store = ...
  
// pobranie zasobu
PluginStoreResource resource = store.read("some/path/file.xml")
if(resource == null){
    // zasób nie istnieje
    return;
}
  
// odczyt i poprawne zamknięcie
InputStream input = resource.getInputStream();
try{
    // odczyt/kopiowanie etc.
}
finally{
    input.close();
}

 

Usuwanie zasobów:

PluginStore store = ...
  
// usunięcie pojedynczego zasobu
store.delete("some/path/file.xml");
  
// wyczyszczenie całego store'a
store.clear();

 


Integracja wtyczki z systemem

Integracja z interfejsem użytkownika może odbywać się poprzez jego modyfikację lub rozszerzanie już istniejących funkcjonalności.

 

Wpisy w menu

Moduł menu-entry umożliwia dodanie do istniejących menu własnych wpisów o określonych atrybutach. Sekcja zdefiniowana w tym module jednoznacznie identyfikuje menu, do którego chcesz dodać nasz wpis.

System Plus Workflow definiuje następujące sekcje:

 

 

 

 

Wszystkie pozycje w menu mają swój order. Pierwszy systemowy wpis w menu ma order=0, każdy kolejny o 10 większy.

Zaleca się korzystanie z atrybutu order, nawet jeśli kolejność nie jest istotna. Inne wtyczki mogą próbować dodać elementy w pobliżu dodawanego wpisu, co stanie się trudniejsze, jeśli nie zostanie określona odpowiednia kolejność.

 

Kliknięcie na daną pozycję w menu spowoduje wyświetlenie w kontenerze odpowiednim dla każdego z menu zawartości, pobranej ze skonfigurowanego linku.

 

Dodatkowo Kreatory (Wizardy) korzystają z następujących sekcji:

 

 

Nie jest wymagane, aby Kreator posiadał moduł menu-entry. Po instalacji w systemie automatycznie zostanie przypisany do odpowiedniej sekcji.

Widok domyślny

Widok domyślny użytkownika wyświetla się zaraz po zalogowaniu do systemu lub kliknięciu na pozycję Start w menu głównym.

Można umożliwić użytkownikowi wybranie widoku utworzonej wtyczki jako jego widoku domyślnego.

Odpowiedzialny jest za to moduł default-view.

 

Dla każdego zdefiniowanego modułu pojawi się możliwość wyboru tej opcji w wyborze widoku domyślnego:

 

 

 

Create your own Knowledge Base