KROMESCH SÁNDOR APP FELHŐ. API-k és Webszolgáltatások a Cloudban. Magyarországi Web Konferencia November 8.

Hasonló dokumentumok
Webes alkalmazások fejlesztése 8. előadás. Webszolgáltatások megvalósítása (ASP.NET WebAPI)

Java Programozás 11. Ea: MVC modell

PHP II. WEB technológiák. Tóth Zsolt. Miskolci Egyetem. Tóth Zsolt (Miskolci Egyetem) PHP II / 19

Symfony kurzus 2014/2015 I. félév. Controller, Routing

API tervezése mobil környezetbe. gyakorlat

MVC. Model View Controller

Tartalom DCOM. Történeti áttekintés. Történeti áttekintés. Történeti áttekintés. Történeti áttekintés

WCF, Entity Framework, ASP.NET, WPF 1. WCF service-t (adatbázissal Entity Framework) 2. ASP.NET kliens 3. WPF kliens

Bánsághi Anna

Java Programozás 4. Gy: Java GUI. Tipper, MVC kalkulátor

WEBFEJLESZTÉS 2. ADATBÁZIS-KEZELÉS, OSZTÁLYOK

Bevezető. Servlet alapgondolatok

ANDROID ALKALMAZÁSFEJLESZTÉS

Java és web programozás

Stateless Session Bean

Mobil Informatikai Rendszerek

CREATE TABLE student ( id int NOT NULL GENERATED ALWAYS AS IDENTITY PRIMARY KEY, name varchar(100) NOT NULL, address varchar(100) NOT NULL )

Objektumorientált programozás C# nyelven

abkezel.java import java.awt.*; import java.awt.event.*; import javax.swing.*; import java.sql.*; public class abkezel extends JFrame {

Excel ODBC-ADO API. Tevékenységpontok: - DBMS telepítés. - ODBC driver telepítése. - DSN létrehozatala. -Excel-ben ADO bevonása

Java és web programozás

Párhuzamos és Grid rendszerek

Eseményvezérelt alkalmazások fejlesztése II 12. előadás. Objektumrelációs adatkezelés (ADO.NET) Giachetta Roberto

Segédanyag: Java alkalmazások gyakorlat

Biztonság java web alkalmazásokban

RIA Rich Internet Application

Adatbázisok webalkalmazásokban

WWW Kliens-szerver Alapfogalmak Technológiák Terv. Web programozás 1 / 31

Hello World Servlet. Készítsünk egy szervletet, amellyel összeadhatunk két számot, és meghívásakor üdvözlőszöveget ír a konzolra.

Symfony kurzus 2014/2015 I. félév. Security: authentication, authorization, user provider, role-ok, access control, FOS user bundle

Adatbázis rendszerek 7. előadás State of the art

TELJESÍTÉNYMÉRÉS FELHŐ ALAPÚ KÖRNYEZETBEN AZURE CLOUD ANALÍZIS

Objektumorientált programozás C# nyelven III.

Delegátumok C#-ban Krizsán Zoltán iit

Osztályok. construct () destruct() $b=new Book(); $b=null; unset ($b); book.php: <?php class Book { private $isbn; public $title;

C# osztályok. Krizsán Zoltán

Webes alkalmazások fejlesztése 10. előadás. Szolgáltatás alapú rendszerek megvalósítása (ASP.NET WebAPI) Cserép Máté

Flash és PHP kommunikáció. Web Konferencia 2007 Ferencz Tamás Jasmin Media Group Kft

JAVA webes alkalmazások

Web-fejlesztés NGM_IN002_1

Segédanyag: Java alkalmazások gyakorlat

Hálózatbiztonság Androidon. Tamas Balogh Tech AutSoft

Webszolgáltatások (WS)

MicroSigner Közvetítő Szerver fejlesztői dokumentáció

Java bevezet o Kab odi L aszl o Kab odi L aszl o Java bevezet o

Webes alkalmazások fejlesztése. Bevezetés az ASP.NET MVC 5 keretrendszerbe

Modern unit és integrációs tesztelés

Mobil Informatikai Rendszerek

Programozási nyelvek Java

9. MPI

C# nyelv alapjai. Krizsán Zoltán 1. Objektumorientált programozás C# alapokon tananyag. Általános Informatikai Tanszék Miskolci Egyetem

Access adatbázis elérése OLE DB-n keresztül

Grafikus felhasználói felületek. Abstract Window Toolkit, a java.awt és java.awt.event csomagok

Adatbázis alapú rendszerek gyakorlat Adatbázis alapú alkalmazásfejlesztés Java, C# környezetben

Web-technológia PHP-vel

Rétegezett architektúra HTTP. A hálózatfejlesztés motorját a hálózati alkalmazások képezik. TCP/IP protokoll készlet

Amazon Web Services. Géhberger Dániel Szolgáltatások és alkalmazások március 28.

MicroSigner Közvetítő Szerver fejlesztői dokumentáció

Bárányfelhő vagy viharfelhő? A felhő alapú megoldások biztonsági kérdései. Császár Rudolf Műszaki fejlesztési vezető Digital Kft.

Adatbányászat és Perszonalizáció architektúra

WEB-PROGRAMOZÁS II. 1. Egészítse ki a következő PHP kódot a következők szerint: a,b,c,d: <?php. interface Kiir { public function kiir();

Model View Controller alapú alkalmazásfejlesztés

BME MOGI Gépészeti informatika 4.

A hibrid DB cloud biztonsági eszköztára. Kóródi Ferenc Budapest,

PHP5 Új generáció (2. rész)

FITI 2016 Konferencia. Jövőbiztos adatközpontok A sebességnövekedés kihívásai és hatásai

Webes alkalmazások fejlesztése 8. előadás. Webszolgáltatások megvalósítása (ASP.NET WebAPI)

MailMasterPlus API. fejlesztői dokumentáció

Java. Perzisztencia. ANTAL Margit. Java Persistence API. Object Relational Mapping. Perzisztencia. Entity components. ANTAL Margit.

Teszt topológia E1/1 E1/0 SW1 E1/0 E1/0 SW3 SW2. Kuris Ferenc - [HUN] Cisco Blog -

Webszolgáltatások készítése.net alapokon -

BME MOGI Gépészeti informatika 8.

OOP: Java 8.Gy: Gyakorlás

Farkas Szilveszter Magyarországi Web Konferencia Budapest, október 3.

Biztonságos PHP a gyakorlatban

Az osztályok csomagokba vannak rendezve, minden csomag tetszőleges. Könyvtárhierarhiát fed: Pl.: java/util/scanner.java

Bevezetés Működési elv AJAX keretrendszerek AJAX

JavaServer Pages (JSP) (folytatás)

Adabáziselérés ODBC-n keresztül utasításokkal C#-ban

MicroSigner Közvetítő Szerver fejlesztői dokumentáció

Collections. Összetett adatstruktúrák

Overview. Service. Application Activity Activity 2 Activity 3. Fragment. Fragment. Fragment. Frag ment. Fragment. Broadcast Receiver

Az új be- és kimenet könyvtár

ZH mintapélda. Feladat. Felület

Gelle Kitti Algoritmusok és adatszerkezetek gyakorlat - 07 Hasítótáblák

JNDI - alapok. Java Naming and Directory Interface

Vizuális programozás gyakorlat

Reaktív programozás szerver oldalon

I. 288.: Utcai WiFi térkép

Vé V g é r g e r h e a h j a tá t s á i s s z s ál á ak a Runnable, Thread

Hálózatkezelés. Tóth Zsolt. Miskolci Egyetem. Tóth Zsolt (Miskolci Egyetem) Hálózatkezelés / 20

JEE tutorial. Zsíros Levente, 2012

Hello, EJB! Egy egyszerű példa

Cisco Catalyst 3500XL switch segédlet

Google Web Toolkit. Elek Márton. Drótposta kft.

XML adatkezelés I. Az SAX szabvány. Dr. Kovács László Miskolci Egyetem Általános Informatikai Tanszék. XML adatok kezelési lehetőségei

Algoritmusok és adatszerkezetek II.

Objektum Orientált Programozás. 11. Kivételkezelés 44/1B IT MAN

Madarassy László, mérnök, BME - Mobil Innovációs Központ. lmadarassy@mik.bme.hu

SZERVER OLDALI JAVASCRIPT. 3. hét Javascript nyelvi elemek

Átírás:

KROMESCH SÁNDOR APP FELHŐ API-k és Webszolgáltatások a Cloudban Magyarországi Web Konferencia 2014 - November 8.

Kiindulás: Mobil eszközök 1/2 Mobil eszközök 1. Hordozhatók 2. Könnyen kezelhetők 3. Limitált erőforrásokkal rendelkeznek 4. Hozzáférnek az Internethez 1/48

Kiindulás: Cloud 2/2 Szerverek ezrei 1. korlátlan erőforrások 2. hozzáférnek az Internethez 2/48

Kiindulás: Cloud 2/2 Szerverek ezrei 1. korlátlan erőforrások 2. hozzáférnek az Internethez Szerverek száma: Amazon: 150e - 400e Google: 1.500e+ 2/48

Mi a Cloud célja? Applikáció Alkalmazás 3/48

Mi a Cloud célja? Alkalmazás Applikáció Parancs Parancs Parancs 3/48

Mi a Cloud célja? 3/48 Alkalmazás Applikáció DB Parancs Művelet Parancs Parancs

Miért HTTP? 4/48 Miért használjunk web böngészőkhöz kifejlesztett protocolt a Mobil eszközökkel és a Cloud szolgáltatásokkal? HTTP

Miért HTTP? Kliens 5/48 Szerver

Miért HTTP? 5/48 Szolgáltatások Kliens Szerver Erőforrások

Miért HTTP? 5/48 Közös interface Böngésző Szolgáltatások Kliens Szerver HTTP Erőforrások

Miért HTTP? 5/48 Közös interface Böngésző Szolgáltatások Kliens Szerver HTTP Mobil Erőforrások

Miért HTTP? 5/48 Közös interface Böngésző Szolgáltatások Kliens Szerver HTTP Mobil Erőforrások

Miért HTTP? 5/48 Közös interface Böngésző Szolgáltatások Kliens Szerver HTTP Mobil Frameworkok Erőforrások

Miért HTTP? 5/48 Közös interface Böngésző Szolgáltatások Kliens Szerver HTTP Mobil Frameworkok Data marshaling Erőforrások

Miért HTTP? 5/48 Közös interface Böngésző Szolgáltatások Kliens Szerver HTTP Mobil Frameworkok Data marshaling Library-k a HTTP kérések feldolgozáshoz Erőforrások

Miért HTTP? 5/48 Közös interface Böngésző Szolgáltatások Kliens Szerver Erőforrások HTTP Mobil Frameworkok Data marshaling Library-k a HTTP kérések feldolgozáshoz Session kezelés

Miért HTTP? 5/48 Közös interface Böngésző Szolgáltatások Kliens Szerver Erőforrások HTTP Mobil Frameworkok Data marshaling Library-k a HTTP kérések feldolgozáshoz Egyéb eszközök: Load Balancing Session kezelés

Cloud szolgáltatás felépítése 6/48 Cloud Szolgáltatás

Cloud szolgáltatás felépítése 6/48 Cloud Szolgáltatás Parancs HTTP kérés HTTP válasz

Cloud szolgáltatás felépítése 6/48 Kérés Cloud Szolgáltatás Method: GET, POST, PUT Query praraméterek Content Type Parancs Body HTTP kérés HTTP válasz

Cloud szolgáltatás felépítése 6/48 Kérés Cloud Szolgáltatás Method: GET, POST, PUT Query praraméterek Content Type Parancs Body Válasz HTTP Státusz kód Content Type Body HTTP kérés HTTP válasz

TERVEZÉSI / MEGVALÓSÍTÁSI KÉRDÉSEK

Skálázhatóság Vertikális 7/48

Skálázhatóság Vertikális 7/48

Skálázhatóság Vertikális 7/48 Horizontális

Skálázhatóság Vertikális 7/48 Horizontális

Loadbalancing 1/3 8/48 Forgalom...

Loadbalancing 1/3 8/48 Forgalom Hogy routoljuk? HTTP Load Balancer...

Loadbalancing 1/3 8/48 Forgalom Hogy routoljuk? HTTP Load Balancer...

Loadbalancing 1/3 8/48 Round robin statless Forgalom Hogy routoljuk? HTTP Load Balancer...

Loadbalancing 2/3 9/48 Forgalom Hogy routoljuk? HTTP Load Balancer...

Loadbalancing 2/3 9/48 Sticky session Forgalom Hogy routoljuk? HTTP Load Balancer...

Loadbalancing 3/3 10/48 Forgalom HTTP Load Balancer Hogy routoljuk?... DB

Loadbalancing 3/3 Elosztott session 10/48 Forgalom HTTP Load Balancer Hogy routoljuk?... DB

Autoscaling Forgalom 11/48

Autoscaling 11/48 Forgalom... N+1

Autoscaling 11/48 Forgalom... N+1 Intelligencia

PaaS vs IaaS IaaS VM 12/48

PaaS vs IaaS IaaS Toolok DB Kontrollerek VM 12/48

PaaS vs IaaS IaaS Toolok DB Kontrollerek VM Autoscaling 12/48

PaaS vs IaaS IaaS Toolok DB Kontrollerek VM Autoscaling 12/48 PaaS Web App

PaaS vs IaaS IaaS Toolok DB 12/48 PaaS Web App Kontrollerek VM PaaS Autoscaling

AMAZON ELASTIC BEANSTALK

Mit tud egy PaaS Pl.: Amazon Elastic Beanstalk Loadbalancing Auto scaling Multiplatform.NET, Node.js, PHP, Python, Ruby, Java Verzió kezelés Egyszerű deploy Egyszerű hozáférés a többi Amazon szolgáltatáshoz 12/#

Elastic Beanstalk Alkalmazás létrehozás 13/48

Elastic Beanstalk Meta adatok megadása 14/48

Elastic Beanstalk Alkalmazás típusának megadása 14/48

Elastic Beanstalk Forrás beállítása 15/48

Elastic Beanstalk Elérhetőség és környezet beállítása 16/48

Elastic Beanstalk Adatbázis és Virtual Private Cloud beállítás 17/48

Elastic Beanstalk Egyéb beállítások 18/48

Elastic Beanstalk Környezeti válltozók beállítása 19/48

Elastic Beanstalk 20/48

Elastic Beanstalk Alkalmazás dashboard 21/48

Elastic Beanstalk Verziók kezelése 22/48

WEBSZOLGÁLTATÁSOK MEGVALÓSÍTÁSAI

Minta szolgáltatás Kontakt szolgáltatás Kontaktok kezelése Azonosító, Név, Email, Életkor, GET /contact - összes kontakt listája GET /contact/<id> - egy adott kontakt adatai POST /contact - kontakt létrehozása PUT /contact/<id> - kontakt módosítása DELET /contact/<id> - kontakt törlése 23/48

Dynamo BD 24/48 Amazon NoSQL Cloud adatbázis szolgáltatás Dokumentum és kulcs érték pár alapú adat model Háttérben SSD alapú adatárolás Nem tárterület, hanem sávszélesség alapú számlázás Séma felépítés: Table - Item - Attributes Kulcsok: Hash, Hash és Range típusú

JAVA Spring

Java + Spring - Application 25/48 @EnableAutoConfiguration @EnableDynamoDBRepositories @EnableWebMvc @ComponentScan @Configuration public class Application extends RepositoryRestMvcConfiguration { public static void main(string[] args) { SpringApplication.run(Application.class, args); } } https://github.com/skromesch/webkonf2014-java

Java + Spring Konfiguráció @Value("${AWS_ACCESS_KEY_ID}") private String amazonawsaccesskey; @Value("${AWS_SECRET_KEY}") private String amazonawssecretkey; @Bean public AmazonDynamoDB amazondynamodb() { AmazonDynamoDB amazondynamodb = new AmazonDynamoDBClient( amazonawscredentials()); return amazondynamodb; } @Bean public AWSCredentials amazonawscredentials() { return new BasicAWSCredentials(amazonAWSAccessKey, amazonawssecretkey); } https://github.com/skromesch/webkonf2014-java 26/48

Java + Spring Model @DynamoDBTable(tableName = "Contacts") public class Contact { private String id; private String name; //.. @DynamoDBHashKey @DynamoDBAutoGeneratedKey public String getid() { return id; } //... @DynamoDBAttribute public String getname() { return name; } //... } https://github.com/skromesch/webkonf2014-java 27/48

Java + Spring Crud Kontroller 28/48 @EnableScan @RepositoryRestResource(path = ContactRepository.CONTACT_SVC_PATH) public interface ContactRepository extends CrudRepository<Contact, Long>{ public public public public static static static static final final final final String String String String NAME_PARAMETER = "name"; EMAIL_PARAMETER = "email"; AGE_PARAMETER = "age"; CONTACT_SVC_PATH = "/contact"; public Collection<Contact> findbyname( @Param(ContactRepository.NAME_PARAMETER) String name); public Collection<Contact> findbyemail( @Param(ContactRepository.EMAIL_PARAMETER) String email); public Collection<Contact> findbyagelessthan( @Param(ContactRepository.AGE_PARAMETER) int maxage); } https://github.com/skromesch/webkonf2014-java

Java + Spring Kontroller 29/48 @Controller public class CrudController { @RequestMapping( value="/crud/contact", method=requestmethod.get) public @ResponseBody Collection<Contact> getcontactlist() { return contacts.values(); } @RequestMapping(value="/crud/contact",method=RequestMethod.POST) public @ResponseBody Contact addcontact( @RequestBody Contact v) { save(v); return v; } } https://github.com/skromesch/webkonf2014-java

ASP.NET MVC

.NET VS Eszközök - AWS Explorer Elastic Beanstalk 30/48

.NET VS Eszközök - AWS Explorer DynamoDB 31/48

.NET + MVC Model [DynamoDBTable("Contacts")] public class Contact { [DynamoDBHashKey(AttributeName="id")] public string Id { get; set; } [DynamoDBProperty(AttributeName = "email")] public string Email { get; set; } [DynamoDBProperty(AttributeName = "age")] public int Age { get; set; } [DynamoDBProperty(AttributeName = "name")] public string Name { get; set; } } https://github.com/skromesch/webkonf2014-net 32/48

.NET + MVC Kontroller public class ContactController : ApiController AmazonDynamoDBClient client = new AmazonDynamoDBClient(); <appsettings> <add key="awsprofilename" value="webkonf" /> <add key="awsregion" value="us-east-1" /> <add key="clientsettingsprovider.serviceuri" value="" /> </appsettings> config.routes.maphttproute( name: "DefaultApi", routetemplate: "api/{controller}/{id}", defaults: new { id = RouteParameter.Optional } ); https://github.com/skromesch/webkonf2014-net 33/48

.NET + MVC GET Kérés 34/48 public IEnumerable<Contact> Get(){ try { DynamoDBContext context = new DynamoDBContext(client); IEnumerable<Contact> contactqueryresults; contactqueryresults = context.scan<contact>(null); return contactqueryresults; } catch (Exception e) { throw new HttpResponseException(Request.CreateErrorResponse( HttpStatusCode.InternalServerError, e.message)); } } https://github.com/skromesch/webkonf2014-net

.NET + MVC POST Kérés 35/48 public HttpResponseMessage Post([FromBody]Contact contact){ try { DynamoDBContext context = new DynamoDBContext(client); context.save<contact>(contact); return new HttpResponseMessage(HttpStatusCode.OK); } catch (Exception e) { throw new HttpResponseException( Request. CreateErrorResponse( HttpStatusCode.InternalServerError, e.message)); } } https://github.com/skromesch/webkonf2014-net

PYTHON Flask

Python + Flask 36/48 Boto - AWS Elérés if not boto.config.has_section('credentials'): boto.config.add_section('credentials') boto.config.set('credentials', 'aws_access_key_id', str( os. environ.get( 'AWS_ACCESS_KEY_ID' ))) boto.config.set('credentials', 'aws_secret_access_key', str( os.environ.get( 'AWS_SECRET_KEY'))) https://github.com/skromesch/webkonf2014-python

Python + Flask GET Kérés 37/48 @application.route('/contact', methods=['get']) def get_all(): try: contacts_table = Table('Contacts') contacts = contacts_table.scan() res = [] for contact in contacts: res.append({ 'id':contact['id'], 'name':contact['name'], 'email':contact['email'],'age':str(contact['age'])}) return Response(json.dumps(res), mimetype='application/json') except Exception as e: return Response(json.dumps({'message' : str(e)}), mimetype='application/json') https://github.com/skromesch/webkonf2014-python

Python + Flask POST Kérés 38/48 @application.route('/contact', methods=['post']) def create(): try: contacts_table = Table('Contacts') id = uuid.uuid1() name = str(request.form['name']) age = int(request.form['age']) email = str(request.form['email']) res = contacts_table.put_item(data={ 'id' : str(id), 'name' : name, 'email': email, 'age' : age }) if res == True: return Response(json.dumps({'message' : 'saved'}), mimetype='application/json') else: return Response(json.dumps({'message' : 'notsaved'}), mimetype='application/json') except Exception as e: return Response(json.dumps({'message' : str(e)}), mimetype='application/json') https://github.com/skromesch/webkonf2014-python

NODE.JS Express

Node.js + Express Applikáció app.get('/', routes.index); app.get('/contact', contact.list); app.get('/contact/:id', contact.getbyid); app.post('/contact/', contact.create); app.put('/contact/:id', contact.update); app.delete('/contact/:id', contact.delete); http.createserver(app).listen(app.get('port'), function(){ console.log('express server listening on port ' + app.get ('port')); }); https://github.com/skromesch/webkonf2014-nodejs 39/48

Node.js + Express Model Vogels data mapper for AWS https://github.com/ryanfitz/vogels var vogels = require('vogels'); vogels.aws.config.loadfrompath('./config.json'); var Contact = vogels.define('contact', function (schema) { schema.uuid('id', {hashkey: true}); schema.string('email'); schema.string('name'); schema.number('age'); }); Contact.config({tableName: 'Contacts'}); https://github.com/skromesch/webkonf2014-nodejs 40/48

Node.js + Express GET Kérés exports.list = function(req, res, next){ Contact.scan().exec(function(err,contacts){ if (err) { res.statuscode = 500; res.json(err); return; } else { res.json(contacts); } }); }; https://github.com/skromesch/webkonf2014-nodejs 41/48

Node.js + Express POST Kérés 42/48 exports.create = function(req, res){ var email = req.param("email"); if(email == null){ res.statuscode = 400; res.json({"message":"email parameter missing"}); return; } //... Contact.create({email: email, name: name, age: age}, function (err, acc) { if (err) { res.statuscode = 500; res.json(err); return; } else { res.statuscode = 200; res.json({ message: 'Contact created' }); } }); }; https://github.com/skromesch/webkonf2014-nodejs

PHP ZF2

PHP + ZF2 AWS elérés ZF2-höz https://github.com/aws/aws-sdk-php-zf2 Elérés kontrollerből: protected function _getdynamodbclient(){ $aws = $this->getservicelocator()->get('aws'); $client = $aws->get('dynamodb'); return $client; } https://github.com/skromesch/webkonf2014-php 43/48

PHP + ZF2 JSON Válasz modul.config.php 'view_manager' => array( //Add this config 'strategies' => array( 'ViewJsonStrategy', ), ), https://github.com/skromesch/webkonf2014-php 44/48

PHP + ZF2 Kontroller 45/48 class ContactController extends AbstractRestfulController { protected $collectionoptions = array('get'); protected $resourceoptions = array('get','post','put','delete'); protected $tablename = "Contacts"; public function getlist(){ public function get($id){ } } public function delete($id){ } public function update($id,$data){ public function create($data){ } https://github.com/skromesch/webkonf2014-php } }

PHP + ZF2 GET Kérés public function get($id) { try{ $client = $this->_getdynamodbclient(); $response = $client->getitem(array( "TableName" => $this->tablename, "Key" => array( "id" => array( Type::STRING => $id ) ) )); if(is_null($response["item"])){ return $this->_apierror(404,"not found:".$id); } return new JsonModel($response["Item"]); }catch(\exception $ex){ return $this->_apiexception($ex); } } https://github.com/skromesch/webkonf2014-php 46/48

PHP + ZF2 POST Kérés 47/48 public function create($data){ try{ $client = $this->_getdynamodbclient(); if(!isset($data["name"])){ return $this->_apierror(404,"missing param name"); } //... $response = $client->putitem(array( "TableName" => $this->tablename, "Item" => array( "id" => array(type::string => $this->uuid()), "name" => array( Type::STRING => $data["name"] ), "age" => array( Type::NUMBER => $data["age"] ), "email" => array( Type::STRING => $data["email"] ) ))); return new JsonModel(array("message" => "OK")); }catch(\exception $ex){ return $this->_apiexception($ex); } } https://github.com/skromesch/webkonf2014-php

Összefoglalás Mikor használható? Pl: nem áll rendelkezésre üzemeltetési kompetencia Mikor nem használható? Pl: egyedi rendszer igény esetén Mire használható? Pl: rapid élesítés, kb 10 perc alatt üzemképes Hogyan használható? Feladathoz válasszunk eszközt/eszközöket 48/48

Köszönöm a figyelmet! Kromesch Sándor sandor.kromesch@erise.hu