Jump to: navigation, search

Texo/JSON REST Web Services

Introduction

Texo JSON web services allow you to connect client-side user interfaces to a standard JPA enabled web container. The client side can be based on a RIA library such as sencha/extjs or a mobile web solution. In the future also RCP clients will be supported.

The Texo JSON web service support uses the Texo runtime libraries.

The Texo JSON webservice support the following operations:

  • Retrieve using GET http requests: using queries, requesting individual objects, all instances of a type
  • Delete operation through the HTTP Delete method
  • Update and Insert through POST/PUT

On each request Texo returns a structured response based on a schema. The response contains retrieved data, metadata (like record count), updated objects and result information.

Video/Demo & Example project

Many examples used in this page are based on the example project, which you can find here.

This video demos Texo JSON web service support and shows the setup of the example project.

Quick Start

The quick start uses the EMF library example:

  1. install the texo plugins in your eclipse installation
  2. setup eclipse with a tomcat 7 web server
  3. get the example project and import it into your workspace
  4. add the example project to your newly created server in eclipse
  5. start tomcat
  6. create test data by visiting this url: http://localhost:8080/org.eclipse.emf.texo.web.example/model/library?action=testdata
  7. then you can try several web service calls:
    1. http://localhost:8080/org.eclipse.emf.texo.web.example/jsonws/Writer
    2. http://localhost:8080/org.eclipse.emf.texo.web.example/jsonws/Writer/1
    3. http://localhost:8080/org.eclipse.emf.texo.web.example/jsonws?query=select e from Writer e

To update/insert or delete objects check out the description in the rest of this page.

Defining the web service servlets in web.xml

After downloading the required jar files and placing them in WEB-INF/lib. The next step is to configure your web.xml to make the web service servlets available to the outside world. This can be done with this xml-snippet:

 
	<servlet>
		<servlet-name>TexoDataModelBrowser</servlet-name>
		<servlet-class>org.eclipse.emf.texo.web.example.ExampleModelBrowserServlet</servlet-class>
		<load-on-startup>1</load-on-startup>
	</servlet>
 
	<servlet>
		<servlet-name>TexoJSONWS</servlet-name>
		<servlet-class>org.eclipse.emf.texo.server.web.JSONRestWebServiceServlet</servlet-class>
		<load-on-startup>1</load-on-startup>
	</servlet>
 
	<servlet>
		<servlet-name>TexoXMLWS</servlet-name>
		<servlet-class>org.eclipse.emf.texo.server.web.XMLRestWebServiceServlet</servlet-class>
		<load-on-startup>1</load-on-startup>
	</servlet>
 
	<servlet-mapping>
		<servlet-name>TexoJSONWS</servlet-name>
		<url-pattern>/jsonws/*</url-pattern>
	</servlet-mapping>
 
	<servlet-mapping>
		<servlet-name>TexoXMLWS</servlet-name>
		<url-pattern>/xmlws/*</url-pattern>
	</servlet-mapping>

Response Model

When doing a request, Texo will return JSON which follows a specific model, either the domain model or a special Texo response model. The response model is defined by this ecore file. There are 3 types which can be returned:

  • ErrorType: returned when an error occurs, it contains a message, stacktrace and additional information
  • ResponseType: is returned for a retrieval/GET operation for a set of objects, when a single record is requested (see specific section on retrieval below), then the record itself is returned, so no specific response type
  • ResultType: is returned for a delete/update/insert operation, it returns the complete objects that have been deleted, inserted or updated.

Update/delete/insert operations can be executed for multiple objects in one request. One request is always executed in one transaction, if one record fails, the operation also fails for the other records and an ErrorType response is returned with a HTML 500 status code.

Testing web service calls from your browser

You can use browser extensions to test web service calls directly from your browser:


Texo-rest-client.png

Retrieve Operation

All retrieve operations use the GET http method.

Individual Object Requests

When a request is done for a single object, like this:

http://localhost:8080/texo/jsonws/library%7CWriter/1

Then the record/object is returned as it is, so no special ErrorType/ResponseType/ResultType is returned.

{
  "author": {
    "_eclass": "library|Writer",
    "db_Id": 22,
    "_id": "22",
    "_proxy": true,
    "_uri": "http://localhost:8080/org.eclipse.emf.texo.web.example/jsonws/library|Writer/22#",
    "_title": "adhibendis ut liberum studio a"
  },-
  "_eclass": "library|Book",
  "category": "MYSTERY",
  "title": "libertatis iustae servitus propria oppressus",
  "db_version": 1,
  "db_Id": 65,
  "_id": "65",
  "pages": 25,
  "_title": "libertatis iustae servitus propria oppressus (25) - Mystery"
}

If the record which is requested does not exist then an ErrorType response is returned with a 404 HTML status code.

All instances of a type

To get all instances of a type, just specify the url with the type names:

The returned json is structured like this:

{
  "endRow": 4,
  "_eclass": "response|ResponseType",
  "totalRows": 5,
  "status": "success",
  "startRow": 0,
  "data": [{
    "books": [],
    "_eclass": "library|Writer",
    "db_version": 2,
    "db_Id": 1,
    "_id": "1",
    "name": "George Orwell",
    "_title": "George Orwell"
  }, 
  ...
  ...
  {
    "books": [],
    "_eclass": "library|Writer",
    "db_version": 1,
    "db_Id": 5,
    "_id": "5",
    "name": "New One",
    "_title": "New One"
  }],
  "_title": "success"
}

Return Information

The returned object has several properties:

  • endRow: the row number of the last row in the result
  • startRow: the row number of the first row in the result
  • totalRows: the total number of rows in the database
  • data: the returned objects

Object MetaData

The example in the previous section shows that the JSON of each object contains metadata. Texo will add these properties to each JSON object which represents a Texo/Model object:

  • _eclass: a unique identification of the EClass: EPackage prefix, EClass name, separated by a |
  • _id: the id of the object
  • _title: a displayable identification of the object, see the next section for a description
  • _proxy: used for references, is set to true if the referenced object has not been read completely yet, in that case the _uri property is also set.
  • _uri: is added to each proxy reference, denotes the uri by which the referenced object can be retrieved.

Querying

Query in the url

You can also do a query like this:

using the query parameter. Some notes:

  • any jpql query is allowed as long the select statement contains one single object
  • a query can be combined with paging parameters (see next section)
  • the query is checked for illegal characters like ', " and ;. This to prevent sql injection.
  • if you want to use values in the query then you need to use query parameters and pass these as query parameters using the prefix "qp.", note that only string parameters are supported, no type conversion is done. An example querystring:
    •  ?query=select e, e.name from Writer e where e.name like :name&firstResult=0&maxResults=5&childLevels=3&qp.name=name2%

(Named) Query in posted json with parameters

Another possibility is to post the query with parameters to the user using a POST/PUT http method. The query and parameters are passed in using a json object like this one:

{
  "_eclass": "request|QueryType",
  "query": "select e, e.name from Writer e where e.name like :name",
  "parameters": [{
    "_eclass": "request|Parameter",
    "name": "name",
    "value": "name2%"
  }]
}

The result of this example (which retrieves both a writer and its name):

{
  "endRow": 10,
  "_eclass": "response|ResponseType",
  "totalRows": 11,
  "status": "success",
  "startRow": 0,
  "data": [
    [{
      "books": [],
      "_eclass": "library|Writer",
      "db_version": 1,
      "db_Id": 3,
      "_id": "3",
      "name": "name2",
      "_uri": "http://localhost:8080/texo/jsonws/library|Writer/3#",
      "_title": "name2"
    }, "name2"],
    [{
      "books": [],
      "_eclass": "library|Writer",
      "db_version": 1,
      "db_Id": 30,
      "_id": "30",
      "name": "name29",
      "_uri": "http://localhost:8080/texo/jsonws/library|Writer/30#",
      "_title": "name29"
    }, "name29"]
  ],
  "_title": "success"
}

And here is an example using a namedQuery defined in jpa:

<source lang="javascript">{
  "_eclass": "request|QueryType",
  "namedQuery": "myTestQuery",
  "parameters": [{
    "_eclass": "request|Parameter",
    "name": "name",
    "value": "name2%",
    "_title": "name"
  }],
  "_title": "select e, e.name from Writer e where e.name like :name"
}

</source>

Query for multiple values

Texo also allows queries which return multiple values, an array of values in json. This is very handy when showing data in a grid which has derived data from other referred-to-entities:

The resulting json contains the data as an array of arrays:

{
  "endRow": 4,
  "_eclass": "response|ResponseType",
  "totalRows": 16,
  "status": "success",
  "startRow": 0,
  "data": [
    [{
      "books": [],
      "_eclass": "library|Writer",
      "db_version": 1,
      "db_Id": 96,
      "_id": "96",
      "name": "ab idonea iudices pari inter",
      "_uri": "http://localhost:8080/org.eclipse.emf.texo.web.example/jsonws/library|Writer/96#",
      "_title": "ab idonea iudices pari inter"
    }, "ab idonea iudices pari inter"],
    [{
      "books": [],
      "_eclass": "library|Writer",
      "db_version": 1,
      "db_Id": 174,
      "_id": "174",
      "name": "atrocibus conscientiae ubicumque regio obnoxii",
      "_uri": "http://localhost:8080/org.eclipse.emf.texo.web.example/jsonws/library|Writer/174#",
      "_title": "atrocibus conscientiae ubicumque regio obnoxii"
    }, "atrocibus conscientiae ubicumque regio obnoxii"],
    [{
      "books": [],
      "_eclass": "library|Writer",
      "db_version": 1,
      "db_Id": 99,
      "_id": "99",
      "name": "administrationis violent pacto cruciatum aequo",
      "_uri": "http://localhost:8080/org.eclipse.emf.texo.web.example/jsonws/library|Writer/99#",
      "_title": "administrationis violent pacto cruciatum aequo"
    }, "administrationis violent pacto cruciatum aequo"]
  ],
  "_title": "success"
}

Security, Preventing SQL Injection

Texo allows free format queries to be send to the server. This allows great flexibility and is needed to provide advanced UIs with data from the server. On the other hand it allows great freedom in the type of queries send to the server, being more vulnerable for SQL injection.

As a security measure, Texo does not allow the characters ', " or ; in a query, and named variables have to be used for values in a query.

You can prevent free format queries all together by setting a ServiceOption. Please ask on the NewsGroup about this new feature. Instead of free format queries you can then use named queries which have been defined on the server.

Paging Parameters

The above examples returned sets of data. You can pass paging parameters to limit the return to a specific set of rows. This is useful when scrolling through a grid with a large dataset. The following url parameters are supported:

  • firstResult: the starting row number
  • maxResults: the maximum number of rows to return

For example: http://localhost:8080/org.eclipse.emf.texo.web.example/jsonws/library%7CWriter?firstResult=10&maxResults=10

Preventing Count

When returning sets of data Texo will do a count of all records in the database. This count operation can be expensive. To prevent it pass the noCount=true url parameter. For example:

http://localhost:8080/org.eclipse.emf.texo.web.example/jsonws/library%7CWriter?firstResult=10&maxResults=10&noCount=true

Even if no explicit count is done, still Texo will try to be smart and check if there are more records in the database then requested. If so then the endRow property of the returned JSON object will be 1+maxResults.

Proxy

When generating the JSON on the server Texo will not serialized references, the references are serialized as proxy objects. The proxy objects can be recognized because they have a property '_proxy' set to true.

Here is an example of the books EReference of a Writer object from the Library example. All the book references are proxies:

{
  "books": [{
    "_eclass": "library|Book",
    "db_Id": 491,
    "_id": "491",
    "_proxy": true,
    "_uri": "http://localhost:8080/org.eclipse.emf.texo.web.example/jsonws/library|Book/491#",
    "_title": "incitamento quidam quisque suppliciis publicae (381) - Biography"
  }, {
    "_eclass": "library|Book",
    "db_Id": 492,
    "_id": "492",
    "_proxy": true,
    "_uri": "http://localhost:8080/org.eclipse.emf.texo.web.example/jsonws/library|Book/492#",
    "_title": "sunt nullum ea incolumitatis discrimine (382) - Mystery"
  }, {
    "_eclass": "library|Book",
    "db_Id": 493,
    "_id": "493",
    "_proxy": true,
    "_uri": "http://localhost:8080/org.eclipse.emf.texo.web.example/jsonws/library|Book/493#",
    "_title": "patria personae divitiis nemo et (383) - ScienceFiction"
  },
  ....

The _proxy property is set and the _uri points too the url which can be used to retrieve the data of the book (as json).

Child levels

When the objects are serialized to JSON on the server also children/contained objects are serialized with the parents. You can limit the level of children which get included in the parent's JSON using the childLevels parameter:

http://localhost:8080/org.eclipse.emf.texo.web.example/jsonws/library%7CLibrary?childLevels=3

Object Title Configuration

When an object is sent from the server to the client Texo will add a title property which you can use to display a reference to the object in a grid or form. This is an important feature, as without an extra request is needed for each object and EReference displayed in the user interface!

The title definition is done through EAnnotations in the model.

  • Expression: on EClass level an expression can be set using EStructuralFeatures from the EClass (referred to using a ${...} notation). It is set as an EAnnotation with source: 'org.eclipse.emf.texo' and key: 'title'. The value of the EAnnotation contains the expression. See the example in the library.ecore file in the example project:


Texo-title-config.png
  • EAnnotation on one or more EStructuralFeatures: using the same source/key as in the previous bullet but without setting the value. The EAnnottion in this case is only used to flag the EStructuralFeature. If more than one EStructuralFeature is annotated then the ' - ' (dash) is used as the separator.
  • Default: if no expression is used and no EStructuralFeature is annotated then Texo will use the following logic to compute the title, in the following order:
    • uses the first String EAttribute, if not found:
    • uses the first EAttribute, if not found:
    • uses the first EReference

It is possible to use an EReference as part of a title definition, if the reference is set then the title of the referred object is used.

Insert/Update Operation

Insert or update are done through a POST/PUT operation. Texo does not make a distinction between POST/PUT or insert/update from a request perspective. Both types of requests are handled in the same way. If the object which is being posted/put already exists in the database then an update is executed, if it does not exist then an insert is executed. The ResponseType will return the inserted or updated objects.

Also the type which gets inserted/updated is not necessarily inferred from the URL, it is read from the _eclass property in the JSON data itself.

As an example, these URLs will both work fine for update/insert:

Now let's go through some examples:

Insert Example

Create one instance of a writer.

url:

Posted data:

{
  "books":[],
  "_eclass":"library|Writer",
  "name":"George Orwell"
}

Return:

{
  "inserted": [{
    "books": [],
    "_eclass": "library|Writer",
    "db_version": 1,
    "db_Id": 2,
    "_id": "2",
    "name": "George Orwell",
    "_title": "George Orwell"
  }],
  "_eclass": "response|ResultType",
  "updated": [],
  "deleted": [],
  "_title": ""
}

The returned JSON contains the inserted object with all its information. This includes its database id and version number. Also other information can have changed or have been added on the server. The client needs to know about this, so you can update the client object using this same information.


Update/Insert with multiple records

The above example worked with one object, the same can be done for multiple objects by using an array:

The posted data:

[{
  "books": [],
  "_eclass": "library|Writer",
  "name": "Gerge Owell"
}, {
  "books": [],
  "_eclass": "library|Writer",
  "name": "Stephen King"
}]

The result:

{
  "inserted": [{
    "books": [],
    "_eclass": "library|Writer",
    "db_version": 1,
    "db_Id": 1,
    "_id": "1",
    "name": "Gerge Owell",
    "_title": "Gerge Owell"
  }, {
    "books": [],
    "_eclass": "library|Writer",
    "db_version": 1,
    "db_Id": 2,
    "_id": "2",
    "name": "Stephen King",
    "_title": "Stephen King"
  }],
  "_eclass": "response|ResultType",
  "updated": [],
  "deleted": [],
  "_title": ""
}

Updating

Now let's update an object, in the previous example we made some typos in George Orwell's name, let's correct them. To update an object 2 properties need to be set: _id and _eclass. These are used by Texo to find the object in the database.

The posted data:

{
  "books": [],
  _id: 1, 
  "_eclass": "library|Writer",
  "name": "George Orwell"
}

The return:

{
  "inserted": [],
  "_eclass": "response|ResultType",
  "updated": [{
    "books": [],
    "_eclass": "library|Writer",
    "db_version": 2,
    "db_Id": 1,
    "_id": "1",
    "name": "George Orwell",
    "_title": "George Orwell"
  }],
  "deleted": []
}

As you can see now the updated property of the response is set, the db_version has been incremented and the correct name has been set.

Combining New/Existing objects in one request

You can also pass new and existing objects in one array, Texo will automatically detect what to update and what to insert.

The posted data:

[{
  "books": [],
  _id: 1, 
  "_eclass": "library|Writer",
  "name": "George Orwell"
},
{
  "books": [],
  "_eclass": "library|Writer",
  "name": "New One"
}]

The return:

{
  "inserted": [{
    "books": [],
    "_eclass": "library|Writer",
    "db_version": 1,
    "db_Id": 5,
    "_id": "5",
    "name": "New One",
    "_title": "New One"
  }],
  "_eclass": "response|ResultType",
  "updated": [{
    "books": [],
    "_eclass": "library|Writer",
    "db_version": 2,
    "db_Id": 1,
    "_id": "1",
    "name": "George Orwell",
    "_title": "George Orwell"
  }],
  "deleted": [],
  "_title": "George Orwell"
}

Delete Operation

Deletion can be done through different ways:

As an example deletion through the DELETE http method using a url pointing to a single object:

http://localhost:8080/org.eclipse.emf.texo.web.example/jsonws/library%7CWriter/1

the response has the deleted property set:

{
  "inserted": [],
  "_eclass": "response|ResultType",
  "updated": [],
  "deleted": [{
    "books": [],
    "_eclass": "library|Writer",
    "db_version": 1,
    "db_Id": 1,
    "_id": "1",
    "name": "name0",
    "_uri": "http://localhost:8080/org.eclipse.emf.texo.web.example/jsonws/library|Writer/1#",
    "_title": "name0"
  }],
  "_title": ""
}

Mass Delete/Insert/Update Operation

Texo also supports a single request with multiple update operations. This is the so-called action request. It has these characteristics:

  • A POST or PUT http method should be used
  • The body of the request should contain the objects which need to be deleted, inserted and updated, in a so-called action object

The action object (defined by this ecore model) is a json string with the following properties:

  • _eclass set to request|ActionType
  • delete: array of objects to delete
  • update: array of objects to update
  • insert: array of objects to insert

The delete, insert, update actions are done in one transaction on the server. If one fails, the complete transaction fails.

Here is an example of an update/delete/insert of multiple objects in one request.

The url:

The request body, json:

{
  "_eclass": "request|ActionType",
  "delete": [{
    "books": [],
    "_eclass": "library|Writer",
    "_id": "1"
  }],
  "insert": [{
    "_eclass": "library|Writer",
    "name": "test"
  }, {
    "_eclass": "library|Writer",
    "name": "test2"
  }],
  "update": [{
    "_eclass": "library|Book",
    "db_Id": 573,
    "_id": "573",
    "title": "a new title"
  }]
}

The response shows what got deleted, inserted and updated:

{
  "inserted": [{
    "books": [],
    "_eclass": "library|Writer",
    "db_version": 1,
    "db_Id": 2,
    "_id": "2",
    "name": "test",
    "_uri": "http://localhost:8080/org.eclipse.emf.texo.web.example/jsonws/library|Writer/2#",
    "_title": "test"
  }, {
    "books": [],
    "_eclass": "library|Writer",
    "db_version": 1,
    "db_Id": 3,
    "_id": "3",
    "name": "test2",
    "_uri": "http://localhost:8080/org.eclipse.emf.texo.web.example/jsonws/library|Writer/3#",
    "_title": "test2"
  }],
  "_eclass": "response|ResultType",
  "updated": [{
    "author": {
      "_eclass": "library|Writer",
      "db_Id": 116,
      "_id": "116",
      "_proxy": true,
      "_uri": "http://localhost:8080/org.eclipse.emf.texo.web.example/jsonws/library|Writer/116#",
      "_title": "territorii est potestatem Sui non"
    },
    "_eclass": "library|Book",
    "category": "MYSTERY",
    "title": "a new title",
    "db_version": 2,
    "db_Id": 573,
    "_id": "573",
    "pages": 463,
    "_uri": "http://localhost:8080/org.eclipse.emf.texo.web.example/jsonws/library|Book/573#",
    "_title": "a new title (463) - Mystery"
  }],
  "deleted": [{
    "books": [],
    "_eclass": "library|Writer",
    "db_version": 1,
    "db_Id": 1,
    "_id": "1",
    "name": "test2",
    "_uri": "http://localhost:8080/org.eclipse.emf.texo.web.example/jsonws/library|Writer/1#",
    "_title": "test2"
  }],
  "_title": "a new title (463) - Mystery"
}

Error Response

When an error occurs an error HTTP code is returned (404, 500, etc.) and an error JSON string is returned. The JSON contains detailed error information like the error message, the java class of the Exception, the cause and the stacktrace.

Here is an example return:

{
  "message": "Resource not found http://localhost:8080/org.eclipse.emf.texo.web.example/jsonws/library%7CWriter/213123",
  "errorClass": "java.lang.IllegalArgumentException",
  "_eclass": "response|ErrorType",
  "cause": null,
  "_title": "java.lang.IllegalArgumentException",
  "stackTrace": "java.lang.IllegalArgumentException: Resource not found http://localhost:8080/org.eclipse.emf.texo.web.example/jsonws/library%7CWriter/213123\n\tat org.eclipse.emf.texo.server.service.ServiceContext.createResourceNotFoundResult(ServiceContext.java:140)\n\tat org.eclipse.emf.texo.server.service.RetrieveModelOperation.internalExecute(RetrieveModelOperation.java:142)\n\tat org.eclipse.emf.texo.server.service.ModelOperation.execute(ModelOperation.java:47)\n\tat org.eclipse.emf.texo.server.web.WebServiceHandler.doGet(WebServiceHandler.java:88)\n\tat org.eclipse.emf.texo.server.web.WebServiceServlet.doGet(WebServiceServlet.java:55)\n\tat javax.servlet.http.HttpServlet.service(HttpServlet.java:621)\n\tat javax.servlet.http.HttpServlet.service(HttpServlet.java:722)\n\tat org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:304)\n\tat org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)\n\tat org.eclipse.emf.texo.server.store.CurrentEntityManagerRequestFilter.doFilter(CurrentEntityManagerRequestFilter.java:65)\n\tat org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:243)\n\tat org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)\n\tat org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:240)\n\tat org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:164)\n\tat org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:462)\n\tat org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:164)\n\tat org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:100)\n\tat org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:562)\n\tat org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118)\n\tat org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:395)\n\tat org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:250)\n\tat org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:188)\n\tat org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:166)\n\tat org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:302)\n\tat java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)\n\tat java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)\n\tat java.lang.Thread.run(Thread.java:662)\n"
}

Type/EClass Name Qualifying

Texo web services support REST-like url's such as this one to retrieve a single record:

http://localhost:8080/texo/jsonws/library%7CWriter/1

The request type is denoted as this: library|Writer. This is the name space prefix and the eclass name separated by a | symbol. This is to prevent resolving conflicts if there are several epackages with the same eclass name. You can also use this simpler form:

http://localhost:8080/texo/jsonws/Writer/1

This will iterate over all epackages registered in the Texo runtime to find the first EClass with the name Writer. This works fine in most cases as most of the time there are no name clashes.