Jump to: navigation, search

Lyo/AdaptorCodeGeneratorWorkshop

< Lyo

News: An alternative graphical modelling approach is now available. See the Graphical Toolchain Modelling and Code Generation Workshop.

  • The approach supports the modelling of a complete toolchain (including interactions between OSLC servers and clients), as well as a single server and/or client.
  • The prototype is however under development and its features may change over time.

Introduction

The instructions below guide you through the process of developing an OSLC4J provider using a code generator. The generated code is based on a specification of your adaptor model, as defined by an EMF model.

A general demonstration of the code generator can be found here.

Working with a model of the adaptor allows you to work at a higher level of abstraction, without needing to deal with all the technical details of the OSLC standard (such as Linked Data, RDF, etc.). However, a basic understanding of the Linked Data and OSLC concepts remains necessary in order to build a valid model. For an introduction to Linked Data and OSLC, the following resources on open-services.net can be recommended: Linked Data and OSLC Tutorial (2015 Update)

The steps take you from creating an initial Eclipse project to code generate and run your adaptor.

  1. In Setup an OSLC4J project, you will create an empty project that is configured to start developing an OSLC4J adaptor. The instructions target the Lyo code generator. Yet, after these steps, you may also be able to proceed with manually developing your adaptor.
  2. In Develop OSLC4J adaptor through the EMF model, you will specify your adaptor functionality through an EMF model, from which almost complete code will be generated.

But first, make sure your environment is setup appropriately as instructed on Eclipse Setup

Sample Project

As a complement when following the instructions below, this sample OSLC4J project contains a basic but complete adaptor model that can be used as a starting point and/or a reference. The project has a complete setup, as well as a small enough adaptor model to generate complete but compilable code.

Setup an OSLC4J project

Note: This information is based on the tutorial from the MBAT Tutorial on Implementing OSLC Consumers and Providers with OSLC4J

The steps below guide you through the necessary steps of creating an Eclipse project with the necessary configurations to develop any OSLC4J adaptor. The Code Generator is not dependent on these steps, and other approaches to create a project can be used.

In the instructions below, we will refer to the following generic terms, which need to be replaced with the appropriate values for your particular project.

ProjectName: YourProviderProjectName
PackageName: your.basepackage.name
  1. Create a JAVA EE Web Application
    1. File-->New-->Project...
    2. Select Web/Dynamic Web Project
    3. As project name, specify YourProviderProjectName
    4. On the final step of the wizard, check the Generate web.xml... option
    5. Select Finish
  2. Convert project to Maven
    1. Right click on the project, and select Configure --> Convert to Maven Project
    2. In the window that appears, select war under Packaging
  3. Configure the project
    1. Create a folder test at the root of the project
    2. Create the sub-folders launches & resources under the new folder test
    3. Copy the 3 configuration files from the Configuration File Templates into the corresponding folders:
      1. /YourProviderProjectName/pom.xml
      2. /YourProviderProjectName/WebContent/WEB-INF/web.xml
      3. /YourProviderProjectName/test/resources/jetty.xml
      4. If necessary, refresh your Eclipse workspace by right clicking on YourProviderProjectName -> Refresh
    4. Search and replace each of the following keywords with the specific values for your project
      1. ProjectName: YourProviderProjectName
      2. PackageName: your.basepackage.name
    5. If you get the error "Project configuration is not up-to-date with pom.xml", simply right click on the YourProviderProjectName project and select Maven-->Update Project....
  4. Activate Project Facet JAX-RS
    1. Right click the project & Select properties
    2. Select the Project Facets window
    3. Select JAX-RS (REST Web Services)
    4. Click OK to commit the changes.
    5. Right click again on the project & Select properties
    6. select the new JAX-RS sub-window under Project Facets
    7. Set Type: to Disable Library Configuration
    8. Enter JAX-RS servlet class name: org.apache.wink.server.internal.servlet.RestServlet
    9. Under URL mapping patterns:
      1. Remove the existing pattern
      2. Add a new pattern /services/*
      • Note: the above two steps (8 and 9) are no longer available in the Eclipse Mars 4.5 Java EE dialog for the JAX-RS facet. The web.xml file can, of course, be manually edited to make the indicated changes.
    10. Click OK to commit the changes.
  5. Further project configuration
    1. right click the project & select Properties
    2. select Deployment Assembly
    3. Add...
    4. In the new window that appears
      1. select Java Build Path Entries
      2. click Next >
      3. select Maven Dependencies
      4. click Finish
      5. click Apply
      6. click OK
  6. Create a new Run configuration
    1. Select the menu Run-->Run Configurations...
    2. Select Maven Build
    3. Create a new Configuration (Right click on Maven Build -> New)
    4. Enter a name for the new configuration (such as "Launch YourProviderProjectName")
    5. Set the Base directory to ${workspace_loc:/YourProviderProjectName}
    6. Set Goal as jetty:run-exploded
    7. Switch to tab JRE
      1. Set Runtime JRE to Workspace default JRE...
    8. Switch to tab Source
      1. Click Add...
      2. In the new window, select Project and click OK
        1. Check the YourProviderProjectName project
        2. Check the add required projects of selected projects option
        3. Click OK
    9. Switch to Tab Common
      1. Select Shared file
      2. Click Browse...
      3. In the window that appears, select the recently created folder test/launches under the YourProviderProjectName project
      4. click OK
    10. Click Apply
    11. Clock Close

Develop OSLC4J adaptor through the EMF model

From the above steps, you can proceed and manually develop the necessary java classes that correspond to the OSLC resources and the services for your adaptor. Alternatively, you can specify the desired functionality of your OSLC Adaptor - at a higher level of abstraction - through a graphical EMF model. From such a model, the Lyo Code Generator can then produce the bulk of the code necessary to realize the modeled functionality.

Note: The sample OSLC4J project discussed above can also be used as a starting point to build your own model instead.

Instantiate an adaptor model

  1. For convenience, create a new folder adaptorModel in the YourProviderProjectName Project, in order to store the adaptor EMF model in.
  2. Right-click on the adaptorModel folder, and select New-->Other...
    1. In the Wizards window, search and select Adaptorinterface Model, then press Next
    2. choose a suitable file name for the adaptor model, then press Next
    3. For Model Object, select Adaptor Interface, then press Finish
  3. the adaptor model is now created, and is opened using a basic EMF editor.

Define the adaptor model

You can now specify the desired functionality of your OSLC Adaptor through the graphical model.

The adaptor model is an instance of the metal-model illustrated below (For clarity, not all properties are illustrated in the diagram). We will refer to this meta-model to explain how to define your adaptor model instance.

The model consists of 3 main parts:

  • Domain Specification - Modelling the OSLC domain specification(s) to be exposed and/or consumed by the adaptor, as defined in the OSLC Core Specification.
  • Server - modelling the OSLC resources - and their corresponding services - to be exposed by the adaptor.
  • Client - modelling the interactions - as a client - that the adaptor might have with other OSLC servers.

OSLCToolAdaptorMetalModel.png

Define the Domain Specifications

  1. In the EMF editor, expand the model to view the AdaptorInterface instance.
  2. Right-click on AdaptorInterface(1) instance and select New Child --> Specification(2)
    1. This instance is a simple container of domain specifications and namespaces. No properties defined.
  3. Define any number of additional domain specifications. (For example, the OSLC RM domain specification defines the namespace URI of http://open-services.net/ns/rm# with a preferred namespace prefix of oslc_rm. You can here define your own specific domains.) For each such domain specification:
    1. Right-click on the Specification(2) instance and select New Child --> NamespacePrefix(6)
      1. For the newly-created NamespacePrefix, simply provide the prefix for the new domain specification (Note: To view and change properties of a model element, you can (a) right-click on the EMF instance, and select "Show Properties View" or (b) double-click on the instance.)
    2. Right-click on the Specification(2) instance and select New Child --> DomainSpecification(5)
      1. For the newly created DomainSpecification instance, fill-in its properties. (Note that the namespacePrefix property refers to an instance of NamespacePrefix(6))
      2. Define Resource(8) and/or ResourceProperty(7) instances as desired.
      3. Note that a Resource instance can refer to ResourceProperties from any other domainSpecification in the model.

Define the Server

  1. Select the AdaptorInterface(1) EMF instance and configure its Properties.
    1. The properties’ meaning is as follows:
      1. name: the name of your adaptor (for example, use the same name as your project name)
      2. java Class Base Namespace: the name of the base Java root package from which the code of your adaptor will be generated.
        1. Make sure that this value matches your.basepackage.name selected above.
      3. Java Files Base Path: The path of where java files will be generated. (for example, /src/)
      4. Javascript Files Base Path: The path of where javascript files will be generated. (for example, /WebContent)
      5. Jsp Files Base Path: The path of where the Jsp files will be generated. (for example, /WebContent)
  2. Right-click on AdaptorInterface instance and select New Child -->ServiceProviderCatalog(3)
    1. For the newly created catalog, fill-in all its properties as defined according to OSLC.
    2. Note that you can only define 1 catalogue in an adaptor.
  3. Right-click on the ServiceProviderCatalog instance and select New Child -->Publisher(9)
    1. For the newly created Publisher, fill-in all the Publisher properties as defined according to OSLC.
    2. Note that you can only define 1 Publisher for a catalog.
  4. Right-click on the ServiceProviderCatalogue instance and select New Child -->ServiceProvider(10)
    1. For the newly created ServiceProvider, fill-in the ServiceProvider properties (Title, Description) as defined according to OSLC.
    2. (optional) To control the relative URLs used in the ServiceProvider web service, specify the following optional properties:
      1. serviceNamespace - specifies the relative URL for the ServiceProvider JAX-RS Service. For example, "projects" will lead to the url "http://localhost:8080/YourAdaptor/services/projects". The default is "serviceProviders" (leading to the default "http://localhost:8080/YourAdaptor/services/serviceProviders").
      2. instanceID - specifies the relative URL of a single service provider, including the parameter variables necessary to identify a specific service provider. For example, "{projectId}" leads to the url "http://localhost:8080/YourAdaptor/services/projects/1" mapping the value 1 to the projectId parameter in the java code. Other IDs can be "collectionName/{collectionName}/project/{projectName}". The default is "{serviceProviderId}".
    3. Note that you can define one-or-many ServiceProviders for a ServiceProviderCatalogue.
  5. From each of the defined ServiceProviders, proceed down to create and define Services(11) & Capabilities(12).
    1. Make sure you fill-in all properties of each EMF instance you create.
    2. Make sure you satisfy the cardinality of each of the containment relationships as illustrated in the figure above.
    3. When defining the properties of Capabilities(12), make sure you define each of their Resource Types property. (Which are defined either under the Specifiation(2) EMF instance (see section Define right-side of adaptor model), or exist as part of a loaded domain specification (see section Load existing domain specifications).)
    4. (optional) To control the relative URLs used in the web service handling a particular resource, create a BasicCapability with the following properties:
      1. serviceNamespace - specifies whether the relative URL of the resource web service should include the URL of its managing service provider (relativeToServiceProvider), or it should be standalone (independantOfServiceProvider).
      2. instanceID - specifies the relative URL of a single resource, including the parameter variables necessary to identify a specific resource. For example, "{changeRequestId}" leads to the url "http://localhost:8080/YourAdaptor/services/changeRequests/1" mapping the value 1 to the changeRequestId parameter in the java code.

Define the Client(s) Interactions

Currently, the model supports a simple definition of client interactions, by either linking to another adaptorInterface model, or simply listing the set of resources the adaptor expects from its required server.

To define a client interaction with an adaptor for which a model already exists:

  1. right-click on AdaptorInterface(1) instance and select New Child -->Modelled Required Adaptor(14)
  2. For the newly created Required Adaptor instance, fill-in its properties.
    1. Define the URI of the Service Provider Catalog
    2. Define the AdaptorInterface that this client represents.
      • Tips: Instead of modelling all adaptors in a single model, you can instead link to an adaptorInterface defined in another model: (a) right-click in an empty are of the diagram and select the context menu Load Resource... (b) Select Browse Workspace... (c) Select the desired adaptorInterface model that you intend to use. Elements of the loaded model can now be referenced in the adaptor model you are creating.

To define a client interaction with an adaptor that is simply modelled by the set of resources it exposes:

  1. right-click on AdaptorInterface(1) instance and select New Child -->Generic Required Adaptor(14)
  2. For the newly created Required Adaptor instance, fill-in its properties.
    1. Define a name of the server
    2. Define the URI of the Service Provider Catalog
    3. Define the set of Resources(9) that the client expects the server to expose.

Validate the adaptor model

Once the adaptor model is defined, validate it to ensure all required properties are defined as expected.

  1. select and open the adaptor model
  2. Select the menu item Adaptorinterface Editor --> Validate
  3. If any, deal with any error messages that appear.

Generate the adaptor code

Once the adaptor model is defined and validated, you can generate the corresponding code through the following simple step:

Right-click on the adaptor model, and select Acceleo Model to Text --> Generate CodeGenerator

Note: The code generator supports an incremental development of the adaptor model. Any manual changes to the generated code (within designated placeholders) are maintained upon a subsequent change in the adaptor model, and resulting code re-generation.

Upon a successful code generation, all the necessary Java classes for a complete ready-to-run OSLC4J project are produced. The next section gives an overview of the generated code, before proceeding with an explanation of the necessary manual code to be provided.

Browsing the generated code

Besides the AdaptorManager class (see next section), all generated classes have complete functionality, and need not be modified nor complemented with additional manual code. However, the classes contain placeholders that allow the developer to insert additional code and hence modify the generated default code where necessary. such manual code remains intact after subsequent generations, if modifications are placed within the designated placeholders. This allows for the incremental development of the adaptor model, and its resulting code.

  • To illustrate, open a class file in the package your.basepackage.name.resources, and note the following placeholder:
// Start of user code imports
// End of user code
  • Any code entered between these two lines of code is maintained across subsequent generations. In this example, the placeholder is intended for developer-specific imports, but any Java code can be inserted.

The following Java classes are generated based on the adaptor specification model:

  1. Package: your.basepackage.name.resources
    • for each OSLC-resource of relevance to your project, a corresponding Java class is defined. The class includes the appropriate OSLC annotations, instance attributes, getters, setters, etc.
    • Which resource classes are generated? Each resource for which an OSLC-service is defined; as well as - recursively - the resource extending such a resource, and the resources defined for any of its attributes. that is, all resources needed.
  2. Package: your.basepackage.name.services
    • this package contains the JAX-RS classes corresponding to the resource services defined in the model, as well as those for the ServiceProvider and ServiceProviderCatalog.
    • Each JAX-RS class contains the necessary methods that correspond to Query Capabilities, Creation Factories, Dialogs, as well as the CRUD methods to interact with resources - as defined in the adaptor model.
    • Each JAX-RS class contains methods to respond to both HTML and RDF/XML requests.
  3. Package: your.basepackage.name.servlet
    • Contains necessary classes for the project such as ServiceProviderFactory, ServletListener, etc.
  4. Package: your.basepackage.name.clients
    • for each required adaptor, a corresponding Java class is defined.
    • Currently, the class simply provides a GET method for each resource provided by the required server. This class is a starting point to explore the remaining functionality provided by the OslcClient class, and its methods will be expanded in the future.
  5. Package: your.basepackage.name
    • The AdaptorManager class contains the set of methods that will ultimately communicate with the source tool to access its internal data, and eventually expose information as OSLC resources.
    • Only skeletons of the methods are generated. it remains the task of the developer to manual code these methods, as detailed in the next section.
  6. Jsp pages are also generated to handle HTML requests, in the folder webcontent/your/base/package/name. These pages are very useful for debugging purposes:
    • resource presentations
    • query results
    • creation dialogs
    • selection Dialogs
    • ServiceProvider presentations
    • ServiceProviderCatalog presentations

Fill in the internal implementation of the adaptor

The manual code the developer needs to implement is concentrated in a single class - the AdaptorManager class (in the your.basepackage.name package). The methods that need to be provided are:

  • contextInitializeServletListener & contextDestroyServletListener - to implement any application initialisation and termination activities such as establishing a connection to a database.
  • getServiceProviderInfos - returns the set of ServiceProviders
  • for each serviced resource, methods to get, create, search and query such resources.

Run the adaptor

Once the manual code is completed, You are now ready to run the adaptor.

  1. Select the menu Run-->Run Configurations ...
  2. Select the newly created configuration
  3. Click Run

TIPS - Reusing existing domain specifications

While an adaptor model can be completely defined from scratch, it is possible to compose a model from existing model parts, such as predefined standard domain specification models.

  1. In the EMF editor, right-click and select the context menu Load Resource...
  2. Select Browse Workspace...
  3. Select the desired domain specification(s) that you intend to use. (See subsection below for examples)
  4. Press OK.
  5. Elements of the loaded domain specification models can now be referenced in the adaptor model you are creating.

OSLC Core and Domain Specifications

The project adaptormodel in the Lyo Core repository git://git.eclipse.org/gitroot/lyo/org.eclipse.lyo.core.git, contains the following OSLC standard Specifications:

  • OSLC Architecture Management
  • OSLC Change Management
  • OSLC Core Specification

Known bugs and workarounds

Problems when composing models

Did you compose your model from other models (section TIPS - Reusing existing domain specifications) and reference some of its elements in your adaptor model? Currently, the way EMF models reference each other in the xmi files causes problems with the code generator. Before you trigger the code generator, perform the following steps: (These steps need to be repeated if the adaptor model is later changed to include further references).

  1. Copy the workspace location of any loaded resources (EMF models)
    1. In the Project Explorer window, right-click on the AdaptorInterface.xmi file, and select open with --> Other … --> Sample Reflective Ecore Model Editor.
    2. In the newly opened window, right-click and select the context menu Load Resource …
    3. Select Browse Workspace...
    4. Select the domain specification EMF model that you have earlier loaded.
    5. Copy the path to the xmi file selected into the clipboard (it will be something like platform:/resource/org.eclipse.lyo.oslc4j.adaptormodel/model/someSpecification.xmi)
    6. Press Cancel.
  2. In the Project Explorer window, right-click on the AdaptorInterface.xmi file, and select open with --> XML Editor
  3. Search and replace each href entry that refers to your domain specification.
    1. Replace href values that look like href="../../org.eclipse.lyo.oslc4j.adaptormodel/model/someSpecification.xmi#//... with the copied value (which ought to look more like href="platform:/resource/org.eclipse.lyo.oslc4j.adaptormodel/model/someSpecification.xmi#//...").
  4. Repeat these steps for each domain specification model you have loaded and referenced.

Working with the source code

Some hints to work with the source code of the generator.

Make sure you perform the additional steps under Eclipse setup for working with the source code.

Instantiating an adaptor model

When working with the source code, the following steps are needed to create and modify an adaptor model.

  1. Open the adaptorInterface.ecore model in the org.eclipse.lyo.oslc4j.adaptormodel project (folder model)
  2. Expand the ecore model until the AdaptorInterface EClass
  3. Right-click on the AdaptorInterface EClass & select Create Dynamic Instance...
  4. In the dialog that appears
    1. select the folder adaptorModel under the YourProviderProjectName project as the “parent folder”
    2. choose a suitable File name for the adaptor model - AdaptorInterface.xmi is fine.
  5. Right-click on the newly created AdaptorInterface.xmi file, and select open with --> Other... --> EMF Facet Model Browser.

Configuring & running the generator

When working with the source code, the following steps are needed to generate the code.

  1. Define a "run configuration" for adaptor code generation
    1. Select Run --> Run Configurations...
    2. Select Acceleo Application
    3. Press the New launch configuration button
      1. Name: something practical such as Generate YourProviderProjectName
      2. Project: select the org.eclipse.lyo.oslc4j.codegenerator project
      3. Main class: org.eclipse.lyo.oslc4j.codegenerator.main.Generate
      4. Model: the newly created adaptormodel in the YourProviderProjectName project
      5. Target: The YourProviderProjectName project
      6. Runner: Acceleo Plug-in Application
    4. Press Apply
    5. Press Close.
  2. Once you are satisfied with your model, you can generate the adaptor code:
    1. Select Run > Run Configurations …
    2. Select the Generate YourProviderProjectName configuration
    3. Press Run