Porovnávané verzie

Kľúč

  • Tento riadok sa pridal
  • Riadok je odstránený.
  • Formátovanie sa zmenilo.
Komentár: Vrátené z verzie 10

Obsah

Vo verzii 10.1.39-build4 pribudla do knižnice JAPI možnosť aplikačne definovať objekty, ktoré výrazným spôsobom prispievajú k typovo bezpečnej komunikácii pri RPC volaniach. Balíček sk.ipesoft.d2000.d2japi.annotations obsahuje triedy a anotácie pre definovanie mapovania.

...

Anotácia @ReturnValue slúži na previazanie návratovej hodnoty metódy s návratovou hodnotou niektorého z parametrov. Parameter anotácie name = "result" indikuje, že to má byť návratová hodnota 2. parametra zo zoznamu formálnych parametrov kvôli zhode v identifikátoroch. Typ návratovej hodnoty Integer zodpovedá typu formálneho parametra podľa tabuľky v kapitole 4.1.1. Dôležitou podmienkou je, aby bol formálny parameter označený ako vstupno-výstupný.

Anotácia 1. parametra metódy @ParameterValue indikuje, že hodnota tohto parametra má byť premenená na vstupnú hodnotu 1. formálneho parametra (podľa parametra anotácie name = "value"). Typ hodnoty String zodpovedá typu formálneho parametra podľa tabuľky v kapitole 5v kapitole 4.1.1.

Zaujímavý je tiež fakt, že pre 2. formálny parameter (result) nie je definované mapovanie vstupnej hodnoty. V takomto prípade je pri volaní RPC procedúry nastavený 2. parameter na neplatnú (invalidnú) hodnotu.

4.3.2.2. Mapovanie vstupno-výstupného parametra

Blok kódu
languagejava
themeEclipse
@RPC(name = "Square",

...


	parameters =

...


	{
		@Parameter(name = "v", type = ParameterType.real)

...


	})

...


@ReturnValue(name = "v")

...


public Double sqare_1(

...


	@ParameterValue(name = "v") Double value);

...




@RPC(name = "Square",

...


	parameters =

...


	{
		@Parameter(name = "v", type = ParameterType.real)

...


	})

...


public void sqare_2(

...


	@ParameterValue(name = "v") InOut<Double> value);

Metódy square_1 a square square_2 mapujú obidve tú istú RPC (je to dovolené). V porovnaní s predošlým príkladom je však niekoľko odlišností v použití anotácie @RPC a @Parameter:

  • parameter RPC.asynchronous nie je uvedený, lebo je nepovinný a v takom prípade nadobúda automaticky hodnotu false.
  • parameter Parameter.inOut nie je uvedený, lebo je nepovinný a v takom prípade nadobúda automaticky hodnotu true.

Metódy square_1 a square square_2 sa vzájomne odlišujú spôsobom, akým mapujú parameter volania:

  • square_1 rozdeľuje vstupnú a výstupnú časť parametra RPC procedúry na vstupný parameter a návratovú hodnotu metódy.
  • square_2 ponecháva vstupnú aj výstupnú časť parametra RPC procedúry v parametri metódy. Pretože Java ako jazyk nemá vstupno-výstupné parametre, parameter metódy value je deklarovaný s typom InOut<Double>.

Knižnica JAPI použije parameter metódy ako vstupno-výstupný (pri volaní prečíta jeho vstupnú hodnotu a po skončení nastaví jeho výstupnú hodnotu) vtedy, ak sú splnené nasledovné podmienky.

  • formálny parameter RPC procedúry je definovaný ako vstupno-výstupný
  • parameter metódy je deklarovaný s typom InOut<>. Generický parameter typu musí zodpovedať typu formálneho parametra.
  • nepovinný parameter anotácie @ParameterValue.direction nebol uvedený, čiže automaticky nadobudol hodnotu ParameterDirectionType.derived. (Rovnaké správanie by bolo dosiahnuté, keby bol explicitne nastavený na hodnotu derived alebo inout.)

4.3.2.3. Mapovanie synchrónnej procedúry s odloženým vyhodnotením výsledku

...

Blok kódu
languagejava
themeEclipse
RPC(name = "Square",

...


	parameters =

...


	{
		@Parameter(name = "v", type = ParameterType.real)

...


	})

...


@ReturnValue(name = "v")

...


public Future<Double> sqare_3(

...


	@ParameterValue(name = "v") Double value);

Metóda square_3 sa od metódy square_1 odlišuje typom návratovej hodnoty. Keď je typ návratovej hodnoty deklarovaný ako Future, volanie metódy nie je blokujúce, tak ako pri bežnej synchrónnej RPC, ale skončí hneď. Výsledok je uložený vo Future objekte, ktorého .get() metóda zabezpečí synchrónnosť volania.

4.3.2.4. Mapovanie parametra so štruktúrovaným typom

...

Blok kódu
languagejava
themeEclipse
@RPC(name = "Redim",

...


	parameters =

...


	{
		@Parameter(name = "n", type = ParameterType.integer, inOut = false),

...


		@Parameter(name = "r", type = ParameterType.record, recordType = Person.class)

...


	})

...


@ReturnValue(name = "r")

...


public List<Person> redim(

...


	@ParameterValue(name = "n") Integer length,

...


	@ParameterValue(name = "r") List<Person> data);

Metóda redim mapuje RPC, ktorej druhým formálnym parametrom je štruktúrovaná hodnota. Pre správne mapovanie je typ parametra v anotácii nastavený na @Parameter.type = ParameterType.record a nepovinný parameter anotácie @Parameter.recordType = Person.class. Použitá definícia štruktúry SD.Person a jej mapovanie triedou Person pochádza z kapitoly 5.2.1.

Pri použití metódy redim bude pre účely návratovej hodnoty vytvorená nová inštancia typu List<Person> a jej prvky budú nové inštancie typu Person napriek tomu, že majú rovnaký obsah ako inštancie, ktoré boli použité ako parametre.

4.3.2.5. Mapovanie asynchrónneho volania a časovej značky hodnoty

...

Blok kódu
languagejava
themeEclipse
@RPC(name = "SetValue",

...


	asynchronous = true,

...


	parameters =

...


	{
		@Parameter(name = "v", type = ParameterType.time, inOut = false)

...


	})

...


public void setValue(

...


	@ParameterValue(name = "v") Date value,

...


	@ParameterAttribute(name = "v", attributeType = UnivalAttributeType.valueTime)

...


	Long valueTime);

Metóda setValue sa od predošlých príkladov odlišuje tým, že mapuje asynchrónne volanie (RPC.asynchronous = true). To znamená, že z pohľadu používateľa skončí jej volanie okamžite (po odoslaní správy) a nečaká sa na doručenie odpovede o výsledku. Preto tiež asynchrónna metóda nemôže pristupovať ku výstupnej časti parametrov volania a teda nemôže použiť anotáciu @ReturnValue alebo @ReturnAttribute a takisto nemôže nastaviť parametre anotácií ParameterValue.direction a ParameterAttribute ParameterAttribute.direction na hodnoty inout alebo out.

Nová anotácia @ParameterAttribute mapuje vybraný unival atribút – v tomto prípade časovú značku hodnoty (attributeType = UnivalAttributeType.valueTime) . Pozor, nie je dovolené zavolať metódu s null hodnotou null hodnotou tohto parametra – mapovanie null na atribút univalu nie je možné.

V príklade je zámerne použitý iný typ parametra value (java.util.Date) a parametra valueTime (java.lang.Long). Obidva typy je možné rovnako dobre použiť na mapovanie hodnoty vyjadrujúcej „D2000 absolútny čas", ich výber je na tvorcovi mapovania.

4.3.2.6. Mapovanie procedúry s dvomi výstupnými štruktúrovanými parametrami

...

Blok kódu
languagejava
themeEclipse
@RPC(name = "GetDataAndMetadata",

...


	asynchronous = false,

...


	parameters =

...

 
		{
			@Parameter(
				name = "data",

...


				inOut = true,

...


				type = ParameterType.record,

...


				recordType = Person.class),

...


			@Parameter(

...


				name = "meta",

...


				inOut = true,

...


				type = ParameterType.record,

...


				recordType = Metadata.class)})

...


public void getDataAndMetadata(

...


	@ParameterValue(name = "data") InOut<List<Person>> data,

...


	@ParameterValue(name = "meta") InOut<List<Metadata>> meta);

Metóda getDataAndMetadata mapuje procedúru s dvomi vstupno-výstupnými parametrami (2 parametre s inOut = true). V porovnaní s predošlými metódami stojí za povšimnutie:

  • Typ parametra data je InOut<List<Person>>  Generickým   Generickým parametrom kontajnera InOut je generický List, ktorého parametrom je trieda Person, ktorej mapovanie na SD.Person je popísané v kapitole 5 4.2.1.
  • Trieda Metadata mapuje definíciu štruktúry SD.Metadata. Jej definíciu v príkladoch neuvádzame.
  • Inštancia objektu typu List, ako aj inštancie predstavujúce jeho prvky, ktoré sa nachádzajú v kontajneri typu InOut po skončení synchrónneho volania sú vždy iné, ako inštancie, ktoré sa v kontajneri nachádzali na začiatku volania. Toto správanie je vlastnosť knižnice JAPI.

Kotva
_Ref441670798
_Ref441670798
Kotva
_Toc490141259
_Toc490141259
4.3.3. Volanie z ESL do JAPI – príklad s komentármi

V nasledujúcej ukážke bude uvedený zdrojový kód triedy ExampleHandler. Je to aplikačne definovaná trieda, ktorej metódy môžu byť volané ako RPC z prostredia ESL Môžu byť volané aj z prostredia internej Javy a tiež z prostredia JAPI..
import ako RPC z prostredia ESL .

Blok kódu
languagejava
themeEclipse
import sk.ipesoft.d2000.d2japi.annotations.ParameterType;

...


import sk.ipesoft.d2000.d2japi.annotations.eventBinding.Parameter;

...


import sk.ipesoft.d2000.d2japi.annotations.eventBinding.ParameterValue;

...


import sk.ipesoft.d2000.d2japi.annotations.eventBinding.RPC;

...


import sk.ipesoft.d2000.d2japi.annotations.eventBinding.ReturnValue;

...



public class ExampleHandler

...


{

...


	@RPC(name = "Parse",

...


		parameters =

...


		{
			@Parameter(name = "text", type = ParameterType.text, inOut = false),

...


			@Parameter(name = "result", type = ParameterType.integer)

...


		})

...


	@ReturnValue(name = "result")

...


	public Integer parseInt(

...


		@ParameterValue(name = "text") String text)

...


	{
		try
		{
			return Integer.parseInt(text);

...


		}
		catch (NumberFormatException ex)

...


		{
			return null;
		}
	}
}

Metóda parseInt má rovnaké formálne rozhranie a ja tiež funkčne zhodná s RPC s RPC PROCEDURE E.Service.Parse uvedenou v kapitole 5 4.3.2. Pri jej mapovaní boli použité rovnaké anotácie s rovnakým významom ako na metódu Service.parse.

Rozdiel medzi RPC Parse napísanej v ESL a metódou ExampleHandler.parseInt je v tom, že metódu parseInt nie je možné zavolať asynchrónne. Pre takéto volanie by sa JAPI pokúsilo nájsť druhú metódu s rovnakým formálnym rozhraním, ktoré by malo parameter RPC.asynchronous = true.

...

true.

Kotva
_Toc490141260
_Toc490141260
4.3.4. Použitie anotácie CallerInformation

Blok kódu
languagejava
themeEclipse
import sk.ipesoft.d2000.d2japi.annotations.ParameterType;

...


import sk.ipesoft.d2000.d2japi.annotations.eventBinding.Parameter;

...


import sk.ipesoft.d2000.d2japi.annotations.eventBinding.ParameterValue;

...


import sk.ipesoft.d2000.d2japi.annotations.eventBinding.RPC;

...


import sk.ipesoft.d2000.d2japi.annotations.eventBinding.ReturnValue;

...



public class HelloHandler

...


{

...


	@RPC(name = "Hello")

...


	public void hello(

...


	    @CallerInformation(type = CallerInformationType.processHobj) Integer processHobj,

...


	    @CallerInformation(type = CallerInformationType.eventHobj) Integer eventHobj,

...


	    @CallerInformation(type = CallerInformationType.internalJava) Boolean java)

...


	{
	    ...

...


	}

...


}

Anotácia parametra metódy @CallerInformation indikuje, že za hodnotu parametra má byť dosadená informácia o volajúcom. Hodnota parametra type určuje, aká informácia bude dosadená:

  • processHobj – HOBJ procesu (EVH, HIP, DCC), z ktorého bola RPC zavolaná
  • eventHobj – HOBJ objektu typu Event, z ktorého bola RPC zavolaná.
  • internalJava – nadobúda hodnotu true, ak bola RPC zavolaná z prostredia internej Javy.

Kotva
_Toc490141261
_Toc490141261
4.4. Použitie anotovaných objektov

V kapitolách 5 4.2. a 5 4.3. a ich podkapitolách boli vytvorené definície mapovania štruktúrovaných hodnôt (SD.Person  Person  Person) a definície mapovania volania RPC (Service  E E.Service) a späť (trieda ExampleHandler). Ich použitie zjednodušuje mechanickú prácu vytvárania a konverzie unival hodnôt ako aj potrebu manažovať a opakovane používať množstvo HOBJ pre volanie RPC.

Pri používaní anotácií v jazyku Java je dôležité si uvedomiť, že označenie nejakého objektu anotáciou nemá žiadne priame funkčné dôsledky. Napríklad, ak vytvoríme inštanciu triedy ExampleHandler a následne zavoláme jeho metódu parseInt, jej vykonanie prebehne vždy rovnako, bez ohľadu na prítomnosť alebo neprítomnosť anotácie @RPC. Anotácie slúžia iba na to, aby sa kód, ktorý skúma iné časti kódu, vedel lepšie orientovať.

Nasledujúce príklady sa budú odkazovať na triedy vytvorené v príkladoch v kapitolách 5 4.2.1, 5 4.3.2. a 5 4.3.3. Okrem toho budú použité nasledovné objekty:

Blok kódu
languagejava
themeEclipse
D2Connector connector = ... // aktivne spojenie

...


D2Session session = connector.createSession(... // aktivna session

Na konverzie štruktúrovaných hodnôt bude použitý objekt typu UnivalConvertor prístupný cez connector.getDefaultUnivalConvertor().

Kotva
_Toc490141262
_Toc490141262
4.4.1. Príklad volania z JAPI do ESL

V uvedenom príklade je ukážka volania RPC z prostredia JAPI. Príklad sa skladá z inicializačnej časti (kroky 1 a 2), ktorú je potrebné spraviť raz, pri štarte aplikácie, po pripojení sa ku kernelu. Ďalšie kroky (odrážky), sú príklady samotného volania, je možné použiť v ľubovoľnom poradí a opakovať podľa potreby.

  1. Vytvorenie tzv. Event Proxy Factory objektu. V tomto kroku je trieda Service analyzovaná. Nový objekt (factory) v sebe implementuje mapovanie RPC volaní podľa nájdených anotácií. Parametre volania majú nasledujúci význam:
    • Service.class  referencia   referencia na triedu, ktorá definuje mapovanie
    • session

       získanie

       získanie HOBJ a parent HOBJ

      objektu E.Service

      objektu E.Service

      Blok kódu
      languagejava
      themeEclipse
      EventProxyFactory<Service> factory =EventProxyFactory.createFactory(Service.class, session);


  2. Vytvorenie tzv. Event Proxy objektu s využitím factory z predošlého kroku. V tomto kroku vznikne inštancia anonymnej triedy (odvodenej od java.lang.reflect.Proxy), ktorá implementuje rozhranie Service, aby bolo možné volať anotované metódy. Implementáciu tejto triedy generuje JAPI. Parameter volania má nasledovný význam:
    • session

       asociuje

       asociuje vytvorený objekt proxy s touto inštanciou Session – v jej mene budú RPC volané. Môže to byť iná inštancia, ako v kroku 1.

      Blok kódu
      languagejava
      themeEclipse
      Service proxy = factory.createDefault(session);


Nasledujú príklady samotného volania:

  • Jednoduché volanie RPC Parse:

    Blok kódu
    languagejava
    themeEclipse
    Integer result;

...

  • 
    result = proxy.parse("12"); // Integer.valueOf(12)

...

  • 
    result = proxy.parse("ab"); // null


  • Použitie kontajnera InOut<> vo volaní RPC Square:

    Blok kódu
    languagejava
    themeEclipse
    Double value = 5.0;

...

  • 
    InOut<Double> valueContainer = new InOut<>(value);

...

  • 
    proxy.sqare_2(valueContainer);

...

  • 
    Double result = valueContainer.getValue(); 


V aplikáciách, kde dochádza k viacnásobnému pripájaniu a odpájaniu počas životného cyklu aplikácie:

  • Krok 1 stačí spraviť raz, po vytvorení 1. session. Vzniknutú factory môžete považovať za platnú, pokým je aktívny connector. Pre nový connector je potrebné vytvoriť novú factory.
  • Krok 2 je potrebné raz zopakovať pre každú novú session, z ktorej majú byť volané RPC.

Kotva
_Toc490141263
_Toc490141263

...

4.4.2. Príklad volania z ESL do JAPI

V uvedenom príklade je ukážka volania RPC z prostredia ESL do prostredia JAPI a najmä spôsob spracovania a odpovedania na toto volanie. Príklad sa skladá z inicializačnej časti (kroky 1 a 2), po ktorej bude možné adresovať RPC volania do zvolenej session. Krok 3 je inicializáciou v ESL. Krok 4 je samotné volanie, ktorý možno podľa potreby opakovať s ľubovoľnými parametrami.

  1. Vytvorenie tzv. Event Wrapper Factory objektu. V tomto kroku je trieda ExampleHandler analyzovaná. Nový objekt factory v sebe implementuje spracovanie prichádzajúcich RPC volaní a ich mapovanie na volania metód triedy ExampleHandler. Význam použitých parametrov je nasledovný:
    • ExampleHandler.class  referencia  referencia na triedu, ktorá definuje mapovanie
    • session

       preklad mien

       preklad mien

      Blok kódu
      languagejava
      themeEclipse
      EventWrapperFactory<ExampleHandler> factory = EventWrapperFactory.createFactory(ExampleHandler.class, session);


  2. Registrácia inštancie triedy ExampleHandler pre prijímanie RPC volaní do konkrétnej session. Po tomto kroku bude možné adresovať volanie RPC Parse aj do použitej session.

    Blok kódu
    languagejava
    themeEclipse
    ExampleHandler handler = new ExampleHandler();

...

  1. 
    factory.registerNewHandler(session, handler);


  2. Uloženie HOBJ dynamického objektu session, aby bolo možné neskôr volať späť. V tele ľubovoľnej RPC v ESL je možné zistiť adresu (HOBJ procesu a objektu) volajúceho nasledovným spôsobom:

    Blok kódu
    languageesl
    themeRDark
    INT _sessionHobj

...

  1. 
    RPC PROCEDURE Register

...

  1. 
    _sessionHobj := %GetRPCCallerProcess()

...

  1. 
    END Register
    Značky Wiki



  2. Volanie

    RPC

    z prostredia

    z prostredia ESL.

    Namiesto

    mena

    objektu

    je

    použité

    \

    [(0)

    \

    ]

    pretože

    v

    _

    JAPI

    _

    neexistuje

    ekvivalent

    objektu

    typ

    Event.

    Namiesto

    mena

    procesu

    je

    použité

    (_sessionHobj)

    pretože

    session

    je

    v D2000

    v D2000 DODM

    dynamický

    objekt

    typu

    proces

    a na

    a na jeho

    meno

    sa

    nedá

    použiť

    ako

    identifikátor

    v zdrojovom

    v zdrojovom kóde.

...

  1. Blok kódu
    languageesl
    themeRDark
    INT _r
    CALL 

...

  1. [(0)

...

  1. ] Parse("12", _r) ON (_sessionHobj)

...



...

Kotva
1
1
1 D2000 logická hodnota je štandardne mapovaná vymenovaným typom sk.ipesoft.d2000.base.VBool. Pre zjednodušenie použitia je umožnené mapovať typom java.lang.Boolean, pričom je hodnota vOscillate mapovaná ako false.

...

Kotva
7
7
7 Rovnako v dokumente neuvádzame definíciu a mapovanie pre SD.Metadata, lebo nie je potrebné.

Kotva
8
8
8 Môžu byť volané aj z prostredia internej Javy a tiež z prostredia JAPI.