arrow_back history picture_as_pdf This page is read only. You can view the source, but not change it. Ask your administrator if you think this is wrong. ~~Title: REST Service~~ Wir definieren die Business Logik mit [[de:jvx:server:lco:objects|Life-Cycle Objekten]] am Server. Die Zugriffsberechtigung einer Applikation wird durch einen [[de:jvx:server:security:manager|Security Manager]]geprüft. Der Zugriff auf die Business Logik erfolgt üblicherweise via Master- oder SubConnections vom Client. Um die Technologie Unabhängigkeit zu vollenden, steht die Komplette Business Logik einer Applikation auch via REST zur Verfügung. Für die Benützung der REST Services ist die Autentifizierung mit Benutzername und Passwort notwendig. Als Authentifizierungsmechanismus wird [[https://de.wikipedia.org/wiki/HTTP-Authentifizierung#Basic_Authentication|BASIC]] erwendet Die Überprüfung der Daten wird vom Security Manager der Applikation wie gewohnt durchgeführt. Sie müssen für die Integration der REST Services keine Zeile Source Code verändern. =====Funktionsweise===== Die REST Implementierung in JVx wurde mit [[http://www.restlet.org/|Restlet]] umgesetzt. Um die REST Services zu nutzen, muss der Deployment Deskriptor wie folgt konfiguriert werden: <file xml> <servlet> <servlet-name>RestletServlet</servlet-name> <servlet-class>org.restlet.ext.servlet.ServerServlet</servlet-class> <init-param> <param-name>org.restlet.application</param-name> <param-value>com.sibvisions.rad.server.http.rest.RESTAdapter</param-value> </init-param> </servlet> <servlet-mapping> <servlet-name>RestletServlet</servlet-name> <url-pattern>/services/rest/*</url-pattern> </servlet-mapping> </file> Mit dieser Konfiguration stehen folgende Services zur Verfügung: ===== Available services ===== ====Storage Zugriff (CRUD, Meta Data)==== * [[#get-request_select|Select]] * [[#post-request_insert|Insert]] * [[#put-request_update|Update]] * [[#delete-request_delete|Delete]] * [[#options-request_meta_daten|Meta Daten]] ==GET-Request (Select)== Alle Daten abfragen: ''<nowiki>http://server:port/webapp/services/rest/</nowiki>**<fc #BF0000>APPLICATION_NAME</fc>**/**<fc #BF0000>LIFECYCLE_CLASS</fc>**/data/**<fc #BF0000>STORAGE_NAME</fc>**'' Genau einen Datensatz abfragen: ''<nowiki>http://server:port/webapp/services/rest/</nowiki>**<fc #BF0000>APPLICATION_NAME</fc>**/**<fc #BF0000>LIFECYCLE_CLASS</fc>**/data/**<fc #BF0000>STORAGE_NAME</fc>**/**<fc #BF0000>PRIMARY_KEY</fc>**'' Wenn der PK aus mehreren Spalten zusammengesetzt ist, müssen die Query Parameter verwendet werden: ''<nowiki>http://server:port/webapp/services/rest/</nowiki>**<fc #BF0000>APPLICATION_NAME</fc>**/**<fc #BF0000>LIFECYCLE_CLASS</fc>**/data/**<fc #BF0000>STORAGE_NAME</fc>**?**<fc #BF0000>PKCOLUMN=VALUE</fc>**&**<fc #BF0000>PKCOLUMN2=VALUE2</fc>**'' Die Query Parameter können auch verwendet werden, um Filterungen mit Spalten, die nicht PK Spalten sind, durchzuführen. Lesen Sie mehr über [[https://blog.sibvisions.com/2017/10/30/jvx-rest-interface-update/|komplexe Abfrage Parameter]]? ==GET-Response== Der Response enthält immer eine Liste von HashMaps im JSON Format. Als Key wird die Spaltenbezeichnung verwendet. Beispiel: <file json> [ { "ID" : 0, "POST_ID" : 127, "POST_PLZ" : "1127", "STIEGE" : 8, "STRA_ID" : 68, "STRA_NAME" : "Strasse (69)", "HAUSNUMMER" : 37, "TUERNUMMER" : 79 }, { "ID" : 1, "POST_ID" : 50, "POST_PLZ" : "1050", "STIEGE" : 7, "STRA_ID" : 55, "STRA_NAME" : "Strasse (56)", "HAUSNUMMER" : 37, "TUERNUMMER" : 60 }, ] </file> ==POST-Request (Insert)== Insert a new record: ''<nowiki>http://server:port/webapp/services/rest/</nowiki>**<fc #BF0000>APPLICATION_NAME</fc>**/**<fc #BF0000>LIFECYCLE_CLASS</fc>**/data/**<fc #BF0000>STORAGE_NAME</fc>**'' The request requires a HashMap in JSON format. The column name is used as the key. Example: <file json> { "POST_ID" : "0", "STRA_ID" : "0", "HAUSNUMMER" : "9999" } </file> == POST-Response == The response returns the complete record in JSON format: <file json> { "ID" : 1008, "POST_ID" : 0, "POST_PLZ" : "1000", "STIEGE" : null, "STRA_ID" : 0, "STRA_NAME" : "Strasse (1)", "HAUSNUMMER" : 9999, "TUERNUMMER" : null } </file> == PUT-Request (Update) == Update a requord with Primary Key: ''<nowiki>http://server:port/webapp/services/rest/</nowiki>**<fc #BF0000>APPLICATION_NAME</fc>**/**<fc #BF0000>LIFECYCLE_CLASS</fc>**/data/**<fc #BF0000>STORAGE_NAME</fc>**/**<fc #BF0000>PRIMARY_KEY</fc>**'' If the PK is composed of several columns or if the records are not to be identified via the PK, the query parameters must be used: ''<nowiki>http://server:port/webapp/services/rest/</nowiki>**<fc #BF0000>APPLICATION_NAME</fc>**/**<fc #BF0000>LIFECYCLE_CLASS</fc>**/data/**<fc #BF0000>STORAGE_NAME</fc>**?**<fc #BF0000>COLUMN=VALUE</fc>**&**<fc #BF0000>COLUMN2=VALUE2</fc>**'' The request requires a HashMap in JSON format. The column name is used as the key. Example: <file json> { "ID" : "123", "HAUSNUMMER" : "0", "STIEGE" : "0", "TUERNUMMER" : "0" } </file> It should be noted that PK columns are not updated. ==PUT-Response== The response returns the complete record in JSON format: <file json> { "ID" : 0, "POST_ID" : 127, "POST_PLZ" : "1127", "STIEGE" : "0", "STRA_ID" : 68, "STRA_NAME" : "Strasse (69)", "HAUSNUMMER" : "0", "TUERNUMMER" : "0" } </file> ==DELETE-Request (Delete)== Delete exactly one record: ''<nowiki>http://server:port/webapp/services/rest/</nowiki>**<fc #BF0000>APPLICATION_NAME</fc>**/**<fc #BF0000>LIFECYCLE_CLASS</fc>**/data/**<fc #BF0000>STORAGE_NAME</fc>**/**<fc #BF0000>PRIMARY_KEY</fc>**'' If the PK is composed of several columns, the query parameters must be used: ''<nowiki>http://server:port/webapp/services/rest/</nowiki>**<fc #BF0000>APPLICATION_NAME</fc>**/**<fc #BF0000>LIFECYCLE_CLASS</fc>**/data/**<fc #BF0000>STORAGE_NAME</fc>**?**<fc #BF0000>PKCOLUMN=VALUE</fc>**&**<fc #BF0000>PKCOLUMN2=VALUE2</fc>**'' ==DELETE-Response== The response returns the number of deleted records in JSON format (as number): <file json> 42 </file> ==OPTIONS-Request (Meta Data)== Request Meta Data: ''<nowiki>http://server:port/webapp/services/rest/</nowiki>**<fc #BF0000>APPLICATION_NAME</fc>**/**<fc #BF0000>LIFECYCLE_CLASS</fc>**/data/**<fc #BF0000>STORAGE_NAME</fc>**'' ==OPTIONS-Response== The response returns the meta data in JSON format: <file json> { "autoIncrementColumnNames" : [ "ID" ], "columnMetaData" : [ { "allowedValues" : null, "autoIncrement" : true, "dataType" : 3, "defaultValue" : null, "label" : "Id", "linkReference" : null, "name" : "ID", "nullable" : false, "precision" : 10, "scale" : 0, "signed" : true, "sqltype" : 4, "writable" : true }, { "allowedValues" : null, "autoIncrement" : false, "dataType" : 3, "defaultValue" : null, "label" : "Post Id", "linkReference" : null, "name" : "POST_ID", "nullable" : false, "precision" : 10, "scale" : 0, "signed" : true, "sqltype" : 4, "writable" : true }, { "allowedValues" : null, "autoIncrement" : false, "dataType" : 12, "defaultValue" : null, "label" : "Plz", "linkReference" : { "columnNames" : [ "POST_ID", "POST_PLZ"], "referencedColumnNames" : [ "ID", "PLZ"], "referencedStorage" : ".subStorages.postleitzahlen" }, "name" : "POST_PLZ", "nullable" : false, "precision" : 2147483647, "scale" : 0, "signed" : false, "sqltype" : 12, "writable" : false }, { "allowedValues" : null, "autoIncrement" : false, "dataType" : 3, "defaultValue" : null, "label" : "Stra Id", "linkReference" : null, "name" : "STRA_ID", "nullable" : false, "precision" : 10, "scale" : 0, "signed" : true, "sqltype" : 4, "writable" : true }, { "allowedValues" : null, "autoIncrement" : false, "dataType" : 12, "defaultValue" : null, "label" : "Name", "linkReference" : { "columnNames" : [ "STRA_ID", "STRA_NAME"], "referencedColumnNames" : [ "ID", "NAME"], "referencedStorage" : ".subStorages.strassen" }, "name" : "STRA_NAME", "nullable" : false, "precision" : 2147483647, "scale" : 0, "signed" : false, "sqltype" : 12, "writable" : false }, { "allowedValues" : null, "autoIncrement" : false, "dataType" : 3, "defaultValue" : null, "label" : "Hausnummer", "linkReference" : null, "name" : "HAUSNUMMER", "nullable" : false, "precision" : 10, "scale" : 0, "signed" : true, "sqltype" : 4, "writable" : true }, { "allowedValues" : null, "autoIncrement" : false, "dataType" : 3, "defaultValue" : null, "label" : "Stiege", "linkReference" : null, "name" : "STIEGE", "nullable" : true, "precision" : 10, "scale" : 0, "signed" : true, "sqltype" : 4, "writable" : true }, { "allowedValues" : null, "autoIncrement" : false, "dataType" : 3, "defaultValue" : null, "label" : "Tuernummer", "linkReference" : null, "name" : "TUERNUMMER", "nullable" : true, "precision" : 10, "scale" : 0, "signed" : true, "sqltype" : 4, "writable" : true } ], "columnNames" : [ "ID", "POST_ID", "POST_PLZ", "STRA_ID", "STRA_NAME", "HAUSNUMMER", "STIEGE", "TUERNUMMER" ], "primaryKeyColumnNames" : [ "ID" ], "representationColumnNames" : [ "ID", "POST_ID", "POST_PLZ", "STRA_ID", "STRA_NAME", "HAUSNUMMER", "STIEGE", "TUERNUMMER" ] } </file> \\ ==== Call actions ==== The [[jvx:communication:calling_server_action|server-side actions]] can be called directly from the life-cycle object as well as from available business objects. It's also possible to use parameters. * [[#get-request|Action without parameter]] * [[#postput-Request|Action with parameter]] == GET-Request == Call a server-side action (without parameter): ''<nowiki>http://server:port/webapp/services/rest/</nowiki>**<fc #BF0000>APPLICATION_NAME</fc>**/**<fc #BF0000>LIFECYCLE_CLASS</fc>**/action/**<fc #BF0000>ACTION_NAME</fc>**'' Call a method from a business object (without parameter): ''<nowiki>http://server:port/webapp/services/rest/</nowiki>**<fc #BF0000>APPLICATION_NAME</fc>**/**<fc #BF0000>LIFECYCLE_CLASS</fc>**/object/**<fc #BF0000>OBJECT_NAME</fc>**/**<fc #BF0000>ACTION_NAME</fc>**'' == GET-Response == The response returns the return value of the action in JSON format. == POST/PUT-Request == Call a serer-side action (with parameter): ''<nowiki>http://server:port/webapp/services/rest/</nowiki>**<fc #BF0000>APPLICATION_NAME</fc>**/**<fc #BF0000>LIFECYCLE_CLASS</fc>**/action/**<fc #BF0000>ACTION_NAME</fc>**'' Call a method from a business object (with parameter): ''<nowiki>http://server:port/webapp/services/rest/</nowiki>**<fc #BF0000>APPLICATION_NAME</fc>**/**<fc #BF0000>LIFECYCLE_CLASS</fc>**/object/**<fc #BF0000>OBJECT_NAME</fc>**/**<fc #BF0000>ACTION_NAME</fc>**'' The request requires an array of objects populated with the parameters for the action. Example: Action: <file java> public String calculate(Number pFirst, Number pSecond) { return "" + pFirst.intValue() + pSecond.intValue(); } </file> JSON Request: <file json> [123,1] </file> == POST/PUT-Response == The response returns the return value of the action in JSON format. ===== Examples ===== Using php: <file php> $ch = curl_init(); curl_setopt($ch, CURLOPT_URL,'https://<server>/DB/services/rest/League/Standings/data/All'); curl_setopt($ch, CURLOPT_RETURNTRANSFER,1); curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_BASIC); curl_setopt($ch, CURLOPT_USERPWD, "user:password"); //curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 5); $json = json_decode(curl_exec($ch), true); curl_close($ch); </file> \\ [[https://blog.sibvisions.com/2017/10/23/angularjs-4-with-visionx-and-jvx-rest-services/|AngularJS 4 with VisionX and JVx REST services]] [[https://blog.sibvisions.com/2015/06/15/angularjs-with-jvx-in-action/|AngularJS with JVx in action]] \\ **<fs 20px>Note</fs>** For action calls, the correct data types must be used! In general, it is best to dispense with primitive data types, as parameters, and instead of using arrays, the List Interface should be used. It is also recommended to use Number for all numerical values. This avoids problems due to JSON serialization. The life-cycle name should be the fully qualified class name, with package. If only the simple class name is used, JVx will try to find a matching class. If several classes are considered, then no class is used. You can optionally define a search path in the config.xml of the application: <file xml> <application> .. <rest> <search> <path>/com/sibvisions/app/myapp</app> <path>/com/sibvisions/app/myapp/screens/sub/</app> </search> </rest> </application> </file> Additional information about this feature is available in our [[https://oss.sibvisions.com/index.php?do=details&task_id=534|Support System]]