Budapest University of Technology and Economics Department of Measurement and Information Systems Fault Tolerant Systems Research Group

Model Driven Software Development and Service Integration

Lecture Notes and Laboratory Instructions

Oszkár Semeráth Gábor Szárnyas

May 10, 2013 Contents

1 Introduction 6

2 An overview of the development environment7 2.1 Introduction...... 7 2.2 Project management...... 8 2.2.1 Workspace...... 8 2.2.2 Project...... 8 2.2.3 Package Explorer and Project Explorer...... 8 2.2.4 Build in Eclipse...... 9 2.2.5 Copying and linking...... 9 2.2.6 Pictograms...... 9 2.2.7 Subversion...... 9 2.3 User interface...... 10 2.3.1 Workbench...... 10 2.3.2 Editors...... 10 2.3.3 Views...... 10 The Problems view and the Error Log view...... 10 2.3.4 Perspective...... 11 2.3.5 SWT...... 11 2.3.6 Search...... 11 2.4 Configuration...... 11 2.4.1 Bundle...... 11 2.4.2 Build path...... 12 2.4.3 Execution environment...... 12 2.4.4 Run configuration...... 12 2.4.5 The .project file...... 13 2.5 The Java source code editor...... 13 2.5.1 Formatting the source code...... 13 2.5.2 Refactoring...... 13

1 2.5.3 Fixing problems...... 14 2.5.4 Zooming...... 14 2.5.5 Content assist and imports...... 14 2.5.6 Automatic generation of getter and setter methods...... 14 2.6 Plug-in development...... 15 2.6.1 Plug-in...... 15 2.6.2 Runtime Eclipse...... 15 2.6.3 RCP...... 15 2.6.4 Update site...... 16 2.6.5 Install as a plug-in...... 16 2.6.6 The Manifest.MF file...... 16 2.6.7 The plugin.xml file...... 17 2.7 Hotkeys...... 17 2.8 Sources...... 18

3 Eclipse laboratory: step-by-step instructions 19 3.1 Introduction...... 19 3.2 Java project...... 19 3.3 Plug-in project...... 21 3.4 Version control...... 22 3.4.1 Sharing projects...... 22

4 BPMN 25 4.1 Introduction...... 25 4.2 Sources...... 25

5 BPMN laboratory – step-by-step instructions 26 5.1 Simple workflow...... 26 5.2 Complex workflow...... 31 5.3 Tips...... 33

6 Web services 35 6.1 Introduction...... 35 6.2 Remarks...... 35 6.3 Apache Tomcat...... 35 6.4 WSDL...... 36 6.5 JAX-RS...... 36 6.5.1 Jersey...... 36 6.6 JAXB...... 36 6.7 Maven...... 36

2 7 Web services laboratory – step-by-step instructions 37 7.1 Prerequisites...... 37 7.1.1 Eclipse WTP...... 37 7.1.2 Maven...... 39 7.2 Datatypes...... 39 7.3 JAX-WS...... 40 7.4 JAX-RS...... 45 7.4.1 Creating the project...... 45 7.4.2 Dependencies...... 45 7.4.3 Java code...... 45 7.4.4 Deployment...... 46 7.5 JAXB...... 48 7.6 Tomcat Web Application Manager...... 49 7.6.1 Performance monitoring...... 50 7.7 Testing a REST application...... 50 7.8 Google App Engine...... 52 7.9 Tips and troubleshooting...... 52 7.10 Additional materials...... 52 7.10.1 Creating a JSP Servlet...... 52 7.11 Sources...... 55

8 Yakindu 56 8.1 Prerequisites...... 56 8.2 Modeling...... 57 8.3 Code generation...... 60 8.4 Tips...... 64

9 Bonita 65 9.1 Introduction...... 65 9.2 Scripting Reminder...... 65 9.3 Database Integration...... 65 9.4 Web services...... 67 9.4.1 SOA web service...... 67 SoapUI...... 68 9.4.2 REST web service...... 68 9.5 Creating a new connector...... 68

3 10 Introduction to the Eclipse Modeling Framework 76 10.1 About the EMF...... 76 10.2 Description of the task...... 76 10.3 Prerequisites...... 76 10.4 Ecore model: step-by-step...... 76 10.5 Editor: step-by-step...... 79 10.6 Model manipulation: step-by-step...... 80 10.7 Summary...... 82 10.8 General tips...... 82

11 Code generation technologies 84 11.1 JVM based languages...... 84 11.1.1 Scala...... 84 11.1.2 Groovy...... 84 11.1.3 Clojure...... 85 11.2 Code generation with Eclipse technologies...... 85 11.2.1 Xtext...... 85 11.2.2 Xbase...... 85 11.2.3 Xpand...... 86 Xtend (deprecated)...... 86 11.2.4 Xtend (previously called Xtend2)...... 86

12 JPA 88

13 Code generation laboratory 93

14 NoSQL 96 14.1 Neo4j console...... 96 14.2 Embedded mode...... 97 14.2.1 Dependencies...... 97 14.2.2 Java code...... 97 14.2.3 Neoclipse...... 100 14.2.4 Cypher query from Java...... 100 14.3 Server mode...... 101 14.3.1 Using the REST API manually...... 101 14.3.2 Web administration interface...... 101 14.3.3 REST API in Java...... 103 Installing Maven...... 103 Compiling the Neo4j java-rest-binding project with Maven...... 103 Creating the Java application...... 104

4 15 IncQuery 106 15.1 Setup...... 106 15.2 Simple Query Language Tutorial...... 107 15.3 Visualization tutorial...... 109 15.4 Advanced Query language tutorial...... 109 15.5 Validation...... 111 15.6 Derived feature...... 111

5 Chapter 1

Introduction

This document is a collection of technology descriptions and laboratory instructions for the Model Driven Software Development and Service Integration courses. The courses are part of the computer engineering master’s programme „Dependable System Design” held at the Budapest University of Technology and Economics by the Fault Tolerant Systems Research Group (FTSRG). The course home pages are available here:

• Model Driven Software Development: http://www.inf.mit.bme.hu/edu/courses/mdsd • System Integration: http://www.inf.mit.bme.hu/edu/courses/szolgint

If you find any errors, please email it to the authors: Oszkár Semeráth ([email protected]) and Gábor Szárnyas ([email protected]).

6 Chapter 2

An overview of the Eclipse development environment

2.1 Introduction

The following chapter serves as an introduction to the Eclipse Development Environment. Eclipse is used in both the Model Driven Software Development and Service Integration courses.

Figure 2.1: The splashscreen of Eclipse Juno

Eclipse is a free, open-source software development environment and a platform for plug-in development. Members of the Eclipse Foundation include Cisco, IBM, Intel, Google, SAP,Siemens, etc. A list of Eclipse Foundation Members is available here: http://www.eclipse.org/membership/showAllMembers.php. In this section we will cover the basic concepts in Eclipse. Eclipse comes in different editions, e.g. Eclipse IDE for Java Developers, Eclipse IDE for /C++ Developers, Eclipse Modeling Tools, each containing a different set of plug-ins. The Eclipse SDK includes JDT (Java Development Tools) which features a full-blown Java development environment with an advanced editor and debugger. It supports unit testing (JUnit) and different source code analysis techniques. The JDT has its own Java compiler which can compile Java code incrementally. Project homepage: http://www.eclipse.org/jdt/

7 2.2 Project management

2.2.1 Workspace

Eclipse organises the work in workspaces. A workspaces can contain multiple projects. Projects can be organised in working sets. Upon launching, Eclipse prompts you the location of the workspace. You may switch workspace later in the File | Switch Workspace menu. Further reading:

• http://help.eclipse.org/juno/topic/org.eclipse.platform.doc.isv/guide/resInt_workspace.htm • http://help.eclipse.org/juno/index.jsp?topic=/org.eclipse.platform.doc.user/concepts/cworkset.htm

2.2.2 Project

Eclipse organises the work in projects. Projects can have multiple natures, e.g. Java, C++, Plug-in project, etc. You can create a new project in the File | New menu. The project settings are stored in the .project file. Warning: upon creation, the project directory will be the same as the project name. However, if you rename the project, it only edits the .project file and the project directory will not change. To rename the project directory you have to rename it in the file system and import the project. Of course, this is not trivial if you use version control. Thus, when creating projects it’s worthy to think on good project names. Projects can be exported in the File | Export menu. A common way of distributing sample projects is to create a zip file by choosing General | Archive file. You can import an archive file in the File | Import menu by choosing General | Existing Projects into Workspace and using the Select archive file option. Further reading: http://help.eclipse.org/juno/index.jsp?topic=/org.eclipse.platform.doc.isv/guide/resAdv_natures. htm

2.2.3 Package Explorer and Project Explorer

Figure 2.2: The Package Explorer and the Project Explorer in the same workspace

You may want to show the .project file in the Package Explorer. In order to do so, click the downward pointing triangle in the upper right corner, pick Filters... and untick the .* resources checkbox. To show the .project file in the Project Explorer, click the downward pointing triangle in the upper right corner, pick Customize View... and untick the .* resources checkbox.

8 Figure 2.3: The Filters... menu in the Package Explorer

2.2.4 Build in Eclipse

Eclipse’s build philosophy is to always keep the source code and the binary code in synch. In order to do so, Eclipse builds the project automatically upon every save operation. You may turn of the automatic build process by unchecking the Project | Build Automatically menu. However, as a general rule you should not turn the automatic build off.

2.2.5 Copying and linking

Naturally it is possible to add another file to an existing project. It can be done by dragging and dropping it to your project. As a result a dialog window will appear that ask if the file should be copied to the workspace or just referenced (and left it in its original place). In addition to the basic file management this operation is useful for the version control of documents that are edited outside Eclipse. Manual refresh is required if a file changes out of the IDE.

2.2.6 Pictograms

The Package Explorer and Project Explorer uses a lot of different icons and pictograms. You can find the description if these here: http://help.eclipse.org/juno/index.jsp?topic=/org.eclipse.jdt.doc.user/reference/ref-icons.htm

2.2.7 Subversion

Apache Subversion (http://subversion.apache.org/), often abbreviated SVN is a widely used open-source version control system. Eclipse does not include an SVN client by default. You can install the Subclipse plug-in from your Eclipse distribu- tion’s (e.g. Juno’s) update site by following the instructions provided here: http://www.eclipse.org/subversive/. For basic usage you only need the Subversive SVN Team Provider package. Complete the installation and restart Eclipse. Eclise will ask you to install a Subversive Connector. Choose one which is compatible with your SVN server’s version, install and restart Eclipse again. Subclipse pictograms: http://stackoverflow.com/questions/3917925/what-do-the-arrow-icons-in-subclipse-mean

9 2.3 User interface

2.3.1 Workbench

Upon launching, after you choose the workspace location, the workbench window is shown. A workbench window offers perspectives. A perspective contains editors, such as the Java Editor and views, such as the Project Explorer.

2.3.2 Editors

Editors contribute buttons to the global toolbar. You can have several instances of the same editor, e.g. you can have a dozen Java source files open and edited. You may run different editors at the same time, e.g. you can edit Java and XML files in the same workbench. Editors can be associated with a file name or an extension, and this association can be changed by users.

2.3.3 Views

The primary use of views is to provide navigation of the information in the workbench. You can think of a view as a representation of the data in the workbench. Views have a local toolbar. Editors can appear in only one region of the page, whereas views can be moved to any part of the page and minimized as fast views. The default JDT views include the Package Explorer, the Problems, the Console view and others. You can open new views in the Window | Show View menu.

The Problems view and the Error Log view

The Problems view shows the warnings and errors in the workspace’s projects. In the Problems view click on the Downward pointing triangle icon and pick Show | Errors/warnings on selection. The Error Log shows the errors occured in Eclipse. It shows the error message, the date and the plug-in that produced the error.

Figure 2.4: Show error and warning on selection

Further reading:

• http://wiki.eclipse.org/FAQ_What_is_a_view%3F • http://wiki.eclipse.org/FAQ_What_is_the_difference_between_a_view_and_an_editor%3F

10 2.3.4 Perspective

A perspective is a collection and a predefined layout for editors and views created for a special development purpose: Java, Debug, Plug-in Development, SVN Repository Exploring, etc.

2.3.5 SWT

Java applications typically use AWT (Abstract Window Toolkit) or the Swing toolkit to implement graphical user interfaces. While these are proven solutions, both have serious shortcomings:

• AWT uses native widgets, but only provides the ones which are available on all supported platforms. Also, AWT’s architecture implies that the developer has to work on a low level. Hence, AWT is not suitable for modern application development. • Swing provides its own custom widgets and is easily extensible. Swing provides the option of using either a system „look and feel” which uses the native platform’s look and feel, or a cross-platform look and feel that looks the same on all windowing-system. The old Swing implementation suffered from memory consumption and performance problems.

SWT (Standard Widget Toolkit) is a GUI framework that was developed for the Eclipse project by IBM. It uses native components and offers good performance. Today, SWT is maintained by the Eclipse Foundation. Since the SWT implementation is different for each platform, a platform-specific SWT library (JAR file) must be distributed with each application. A number of SWT widgets are available at http://eclipse.org/swt/widgets/.

Figure 2.5: SWT widgets on different platforms

2.3.6 Search • Search in files: press Ctrl+H to display the Search window and choose the File Search tab. If the window has many tabs, the File Search tab may be hidden. The solution is to resize the Search window or use the arrows in the upper right corner to show the rest of the tabs.

2.4 Configuration

2.4.1 Bundle

OSGi components are named bundles. It’s important to note that Eclipse plug-ins are also OSGi bundles.

11 Figure 2.6: The File Search tab may does not appear at first: resize the window or use the arrows

2.4.2 Build path

If a Java project depends on libraries in JAR files, you have to specify the JAR files containing those. In order to do so, you have to add the JAR file to the build path by right clicking on it and picking Build Path | Add to Build Path. By convention, JAR files are typically stored in a directory called lib. You cannot add a directory to the build path: you have to specify the files. If you want to remove a JAR from the build path, you have to find it under Referenced Libraries, right click and choose Build Path | Remove from Build Path. If you right click anywhere under the project and choose Build Path | Configure Build Path..., you can specify the source folders and the requires libaries.

2.4.3 Execution environment

In the Window | Preferences dialog click Java | Installed JREs. You can add new execution environments and pick the default one.

2.4.4 Run configuration

Eclipse stores the launch settings in run configurations. By default, run configurations are only saved in the workspace. If you want to save or share your run configurations, go to the Run Configurations... (under the Run button or right click on the project and under Run As). On the Common tab choose Shared file in Save as group. If you run multiple programs, you can switch between them by clicking the terminal-shaped icon (called Display selected console).

12 2.4.5 The .project file

There is a configuration file in every Eclipse project named .project. To make the .project file visible from Eclipse, refer to the Package Explorer and Project Explorer section. At first this defines the tool set that works with the project by naming the natures applied to them. For example the plug-in projects have the following natures:

org.eclipse.jdt.core.javanature org.eclipse.pde.PluginNature

Secondly it defines the builders that run after every save. In plug-in projects Eclipse builds the Java code, the MANIFEST.MF and the plugin.xml with the following configuration:

org.eclipse.jdt.core.javabuilder org.eclipse.pde.ManifestBuilder org.eclipse.pde.SchemaBuilder

2.5 The Java source code editor

Right click the left bar in the source code editor and pick Show Line Numbers.

2.5.1 Formatting the source code

In a modern IDE you rarely have to format the code by hand. In Eclipse, right click in the editor and pick Source | Format. Hotkey: Ctrl+Shift+F.

2.5.2 Refactoring

You often need to rename classes, methods and variables. Doing this by hand is an error-prone method: you may forget to rename some occurences of the renamed item. The rename refactoring technique takes care of all occurences of the renamed item. To use it, right click on the renamed item and pick Refactor | Rename.... Type the desired name and press Enter. Hotkey: Alt+Shift+R.

13 2.5.3 Fixing problems

JDT has a very useful feature called Quick fix: if there is an error or warning in the source code, it suggests common ways of fixing it (e.g. if you forgot assign a value to an undefined variable, it will define it). Hotkey: Ctrl+1.

2.5.4 Zooming

By default, Eclipse does not provide zooming in the editor. You can change the font size by going to Window | Preferences. Pick General | Appearance | Colors and Fonts, and edit Basic | Text Font.

2.5.5 Content assist and imports

You can access the content assist by pressing Ctrl+Space. Press Enter to pick you choice. If you pick an item that has to import a package, the appropriate import instructinon will appear between the imports. Sometimes you may end up with lots of unused imports: right click and pick Source | Organize Imports or press Ctrl+Shift+O. Pay attention to the package names. For example, the List class is available both in java.awt and java.util.

Figure 2.7: Some classes are available in more packages

You can use the content assist by only typing the abbreviation of the desired item. For example, if you have java.io.InputStreamReader imported, you can type ISR and the content assist will propose InputStreamReader. If you want to overwrite an item (class name, method name) with the content assist, hold the Ctrl button when you press Enter to pick your choice. There is a lot of predefined template available in the Window | Preferences dialog under Java | Editor | Templates. For example, you can type sysout to get system.out.println();. You can use templates for control structures, you can define cycles with for, while, do, foreach and so on. Similarly, you can define conditional statement with if, ifelse and switch. Tip: Organize Imports can also be used to add missing imports. If the class is available in multiple packages, Eclipse will prompt you to choose between them.

2.5.6 Automatic generation of getter and setter methods

Since the Java language lacks properties, you often have to write getter and setter method for the fields you want to access. Fortunately, you can generate them: right click in the source file and pick Source | Generate Getters and Setters.... Similarly, you can generate the constructor, the toString method and so on. If you have only a few properties, there is a quicker way. While typing getVariableName or setVariableName, use the Content Assist (Ctrl+Space), pick the desired method and press Enter. The appropriate method is generated.

14 2.6 Plug-in development

Multiple pre-compiled editions are available at the home page of Eclipse (http://www.eclipse.org/downloads/). One support C/C++ development, an other aids the testing of software. This IDE is not limited to support those popular field of use; it is designed to be as customisable as possible. It can be used for example as a LaTeX editor, as a host of custom enterprise software (e.g. accounting) or even as a note sheet editor (http://mit.bme.hu/~rath/pub/ theses/diploma_harmathd.pdf). So feel free to look for the tools that support your goals. If you’re interested in the topic, the FTSRG has two related courses to offer:

• Eclipse Technologies: http://www.inf.mit.bme.hu/edu/courses/eat • Eclipse Based Development and Integration: http://www.inf.mit.bme.hu/edu/courses/eafi

2.6.1 Plug-in

Eclipse’s main strength is the possibility of creating and installing custom Eclipse plug-ins. Some useful ones are:

• TeXlipse (http://texlipse.sourceforge.net/): „a plugin that adds Latex support to the Eclipse IDE.” TeXlipse provides incremental compiling and easy navigation between the TeX source and the generated PDF. • FindBugs (http://findbugs.sourceforge.net/): „a program which uses static analysis to look for bugs in Java code”. • PMD (http://pmd.sourceforge.net/): „PMD is a source code analyzer. It finds unused variables, empty catch blocks, unnecessary object creation, and so forth.”

FindBugs and PMD are widely used tools. They’re also part of the Software Verification Techniques course (http: //www.inf.mit.bme.hu/edu/courses/szet/) of the „Dependable System Design” master’s programme held in the autumn semester.

2.6.2 Runtime Eclipse

The Eclipse plug-ins run in an Eclipse instance. If new plug-ins are developed (as Plug-in projects) in an Eclipse instance (called host Eclipse), there should be an Eclipse instance that can run them as a part of it in a new empty workspace. This so called runtime Eclipse contains the plug-ins installed to the host Eclipse and the ones developed in the host Eclipse. A runtime can be started with the Run button. The range of the applied plug-ins can be reduced in the run configuration. It is possible to install developed plug-in projects (see: Install as a plug-in).

2.6.3 RCP

Eclipse RCP (Rich Client Platform) „is a platform for building and deploying rich client applications. It includes Equinox, a component framework based on the OSGi standard, the ability to deploy native GUI applications to a variety of desktop operating systems, such as Windows, and Mac OSX and an integrated update mechanism for deploying desktop applications from a central server.” Along successful open-source projects, RCP is often used for making highly specialised software for organisations. Popular RCP applications include the following:

15 • ECUTE (http://sourceforge.net/apps/mediawiki/sblim/index.php?title=Ecute): „ECUTE stands for Extensible CIM UML Tooling Environment. It is a family of tools that support all phases of the development of CIM models, CIM providers, and CIM client applications.‘’ ECUTE is used in the BSc specialisation programme „Information Technologies” on the Intelligent Systems Surveillance (https://www.inf.mit.bme.hu/edu/bsc/irf) course. • XMind (http://www.xmind.net/): a mind mapping software. • Vuze, formerly known as Azureus (http://www.vuze.com/): a BitTorrent client.

In the Model Driven Software Development and Service Integration courses we use the following RCP applications:

• Bonita Open Solution: http://bonitasoft.com/ • Yakindu: http://statecharts.org/

For more RCP applications, visit the following links:

• http://www.eclipse.org/community/rcpos.php • http://www.eclipse.org/community/rcpcp.php

The popular UML and BPMN modelling tool, Visual Paradigm can also be integrated to Eclipse: http://www. visual-paradigm.com/product/vpuml/provides/ideintegration.jsp. Further reading: http://www.eclipse.org/home/categories/rcp.php.

2.6.4 Update site

Update sites are used to install new features to the Eclipse application. You can install new applications in the Help | Install New Software... menu by selecting the update site and the installed components. After the installation completes, it prompts you to restart Eclipse. If you don’t want to restart yet, you can restart Eclipse later by clicking File | Restart.

2.6.5 Install as a plug-in

Tutorial: http://www.vogella.com/articles/EclipsePlugIn/article.html#deployplugin_direct

2.6.6 The Manifest.MF file

The plug-in project contains a folder named META-INF. This folder has a file named MANIFEST.MF that describes the relations of the packages of this project with the other packages. In simple words, it defines which (Java) package is visible as you edit the source files in this project, and which package you want to make visible to other projects. The content this file looks like the following:

• Version numbers of the MANIFEST.MF:

Manifest-Version: 1.0 Bundle-ManifestVersion: 2

• Names and versions. This can be edited at the Overview page of the in the Plug-in Editor. An example content:

16 Bundle-ManifestVersion: 2 Bundle-Name: JPADataCompileButton Bundle-SymbolicName: hu.bme.mit.mdsd.generatebutton;singleton:=true Bundle-Version: 1.0.0.qualifier

• Required target platform that can run this bundle:

Bundle-RequiredExecutionEnvironment: JavaSE-1.6

• After this, the configuration file enumerates the required bundles with optional minimal version requirement. This can be edited in the Dependencies page of the Plug-in Editor. An example:

Require-Bundle: org.eclipse.ui, hu.bme.mit.mdsd.erdiagram;bundle-version="1.0.0", hu.bme.mit.mdsd.codegenerator;bundle-version="1.0.0", org.eclipse.core.runtime;bundle-version="3.8.0"

• The following section declares the exported packages. This can be edited at the Runtime page of the Plug-in editor.

Export-Package: ERDiagram, ERDiagram.impl, ERDiagram.util

2.6.7 The plugin.xml file

An eclipse plug-in is an OSGi bundle that (usually) connects to other bundles through an extension point mechanism. An extension point defines the interface and an extension defines a subscription to that arbitrary interface. The plugin.xml configuration file contains those information. This configuration can be edited in the Extension page of the plug-in editor. An example subscription that handles a GUI event:

2.7 Hotkeys

As every modern IDE, Eclipse defines a great number of hotkeys. We gathered some useful ones here:

• List the available hotkeys: Ctrl+Shift+L. • Quick fix: Ctrl+1

17 • Content assist: Ctrl+Space • Organize imports: Ctrl+Shift+O • Autoformatting of source code: Ctrl+Shift+F • Run: Ctrl+F11 • Navigate between tabs: Ctrl+Page Up, Ctrl+Page Down • Rename refactoring: Alt+Shift+R • Find/Replace: Ctrl+F, use Ctrl+K to iterate through the results. • Seach: Ctrl+H

You can edit the hotkeys in the Window | Preferences menu, in General | Keys. For some plug-ins (e.g. TeXlipse), the hotkeys don’t appear at first: click the Filters... button and untick the Filter uncategorized commands checkbox.

2.8 Sources

• Our own experience from Project Laboratories, etc. • University courses: Eclipse Technologies (http://www.inf.mit.bme.hu/edu/courses/eat), Eclipse Based De- velopment and Integration (http://www.inf.mit.bme.hu/edu/courses/eafi), Model Driven Software Devel- opment (http://www.inf.mit.bme.hu/edu/courses/mdsd), Service Integration (http://www.inf.mit.bme.hu/ edu/courses/szolgint) • http://www.eclipse.org/documentation/ • http://theshyam.com/2009/07/eclipse-productivity-shortcuts/ • http://www.openlogic.com/wazi/bid/221090/Eclipse-productivity-tips • http://rithus.com/eclipse-productivity-tips

18 Chapter 3

Eclipse laboratory: step-by-step instructions

3.1 Introduction

We will demonstrate Eclipse on a simple task. We create a Java project and then extend it to a plug-in project. After that, we import a plug-in project which puts a button on the Eclipse toolbar and configure it to print the output of our own plug-in project.

3.2 Java project

Go to File | New | Other.... Here you can choose any type of projects your Eclipse supports. For now, create Java Project.

1. Name to project to hu.bme.mit.inf.carhandler and click Finish. 2. Right click on the project name and choose New | Package. Name the package to hu.bme.mit.inf.cars. 3. Right click the package and choose New | Class. Name the class to Car.

public class Car { private String numberplate; private int yearOfManufacture; private double acceleration; }

Right click and go to the Source menu. You can access formatting, refactoring and generation tools here. Use the following:

• Generate Constructor using Fields... • Generate Getters and Setters... • Generate toString... • Format

4. Create a new class named CarFleetPrinter. This time, tick public static void main(String[] args) checkbox so the main function is generated automatically. You can create the main method later as well, using the main template and content assist (Ctrl+Space). Write the following code. Hint:

19 • Type /** and press Enter to Javadoc. • Use Ctrl+1 to use the appropriate package to import. • Use the content assist to suggest a default name (car) for the collection. • Type LL and use the content assist to find the LinkedList class. • Use the foreach and the sysout templates.

/** * Car dealer program. * @param args Arguments */ public static void main(String[] args) { String manifest = "The car fleet consists of:\n";

List cars = new LinkedList(); Random random = new Random(); for (inti=0; i < 10; i++) cars.add( new Car( "MIT-" + random.nextInt(10) + random.nextInt(10) + random.nextInt(10), 2000 + random.nextInt(13), 3.0 + random.nextDouble() *4 ) );

for (Car car : cars) { if (car.getAcceleration() <5){ manifest += "- Car: " + car +"\n"; } }

System.out.println(manifest); }

5. Use the Rename refactoring technique to rename the class from Car to SportsCar.

6. Select the following part:

new Car( "MIT-" + random.nextInt(10) + random.nextInt(10) + random.nextInt(10), 2000 + random.nextInt(13), 3.0 + random.nextDouble() *4 )

Use the Extract method refactoring technique to extract it to a method named generateRandomCar. 7. Select the whole main method except the last line (System.out.println(manifest)). Use the Extract method technique again to extract it to a method named getCarManifest.

8. The result looks like this:

public static void main(String[] args) { String manifest = getCarManifest();

System.out.println(manifest); }

20 private static String getCarManifest() { String manifest = "The car fleet consists of:\n";

List cars = new LinkedList(); Random random = new Random(); for (inti=0; i < 10; i++) cars.add( generateRandomCar(random) );

for (Car car : cars) { if (car.acceleration<5){ manifest += "- Car: " + car +"\n"; } } return manifest; }

private static Car generateRandomCar(Random random) { return new Car( "MIT-" + random.nextInt(10) + random.nextInt(10) + random.nextInt(10), 2000 + random.nextInt(13), 3.0 + random.nextDouble() *4 ); }

9. To run the project, right click and pick Run As | Java Application.

3.3 Plug-in project

1. Import the hu.bme.mit.inf.car.carbutton project from the CarButton.zip file. Use the File | Import menu and choose General | Existing Projects into Workspace and use the Select archive file option.

2. Inspect the plugin.xml and META-INF/MANIFEST.MF file. The most interesting for now are the Extensions tab.

3. Run the project by right clicking the project and picking Run As | Eclipse Application. A new Eclipse instance called „Runtime Eclipse” will start with the plug-in. Close the welcome Window. Observe the Print! button on the toolbar.

4. Close the Runtime Eclipse.

5. We would like to extend our Java project to a plug-in project. Right click the hu.bme.mit.inf.carhandler project and choose Configure | Convert to Plug-in Projects.... Click Finish.

6. Go to the carhandler project’s newly created MANIFEST.MF file. Pick the Runtime tab. Observe the Exported Packages. Later, you can add additional packages if necessary.

7. Go to the carbutton project’s MANIFEST.MF file. Pick the Dependencies tab. 8. Click Add. An empty list will show. However, as soon as you start typing car, the hu.bme.mit.inf.carhandle (1.0.0.qualifier) package will show. Click OK.

21 9. Go to the hu.bme.mit.inf.car.carbutton package’s PrintTheCarHandler file. Inspect the showMessage method which shows a message in a dialog window.

10. In the execute method use showMessage to show the car fleet’s data.

showMessage(CarFleetPrinter.getCarManifest());

Use Quick Fix take care of the missing CarFleetPrinter import and change the visibility of the method.

11. Run the plug-in project. This time, the Print! button will show the cars in the fleet.

Figure 3.1: The message shown in the plug-in project.

3.4 Version control

From the Window | Open Perspective | Other... pick the SVN Repository Exploring perspective. Use the green plus icon (New Repository Location) to add a new repository. (You can also import from the File | Import menu with the SVN | Project from SVN option.) & Specify the URL and fill the authentication data appropriately. If you’re working on a private computer, it’s recommended to save the authentication data. Click Finish. For now, don’t bother with the password recovery feature.

3.4.1 Sharing projects

If you have configured a Subversion repository, you can easily share your projects. Right click on the project name and pick Team | Share Project.... Choose SVN and choose your repository location and specify the target URL. Pay attention to always include the project name as the last directory in the path. (Warning: if you use the Browse... button, it will not be added automatically). Click Finish. In the Commit window fill the commit message and click OK. If you ever decide to stop using version control for a project (e.g. your version tracking got messed up), go to right click menu and choose Team | Disconnect. When Eclipse prompts you to confirm the question, choose the Also delete the SVN meta-information from the file system. which deletes the hidden .svn directories. You can commit files by choosing Team | Commit..., update files by Update. You can also make good use of the Revert and Revert to commit options. If more than one person works on a file, a conflict can emerge.

22 Figure 3.2: Use the first option when disconnecting from SVN.

Figure 3.3: Conflicting resources

23 Figure 3.4: Resolving the conflict in the Team Synchronizing perspective.

To resolve the conflict, use the Team Synchonizing perspective or right click on the file and choose Team | Edit Conflicts. Further reading: http://help.eclipse.org/juno/index.jsp?topic=/org.eclipse.platform.doc.user/tasks/tasks-115.htm

24 Chapter 4

BPMN

4.1 Introduction

BPMN (Business Process Model and Notation) is a widely used graphical representation for specifying business processes in a business process modell. On the Service Integration course, we will use Bonita as our BPMN editor and workflow framework. Bonita is an Eclipse RCP application.

Figure 4.1: The logo of BonitaSoft

4.2 Sources

• http://www.bonitasoft.com/ • http://www.bpmn.org/

25 Chapter 5

BPMN laboratory – step-by-step instructions

In this laboratory, we will create the workflow of an application store. In the application store the users can browse and upload applications. On the Model Driven Software Development and Service Integration Courses In 2012, the teams had to design and implement the workflow of an application store.

5.1 Simple workflow

1. Start Bonita Studio. Bonita will prompt you to register. You can choose to skip it but it’s highly recommended to register because registration provides access to well-made official tutorials and thorough documentation.

Figure 5.1: The opening screen of Bonita

26 2. Create a new process from Process | New.

3. A simple process will show with only a start event and a human task. Click on the process, choose the Pool page and click the Edit...* button. Rename the process to Browse Application. 4. Click the Step1 task and look at it’s properties on the General tab. On this tab, you can set the execution- specific properties of the process, e.g. it’s Name and Task type. Rename the task to Acknowledge. 5. Add an end event to the workflow. Connect the Acknowledge to the end event.

Figure 5.2: The Browse Application process

6. Let’s create a graphical user interface for this task. Choose the Application tab. On the Entry Pageflow page click Add.... Click Finish.

7. A graphical editor will appear. Add a message to the top of the form. Edit the properties of the message element on the Data page. You can edit plain text or HTML code. Type Hello world!.

8. Click the Run button or choose your process in the Run | Run menu. The generated web page will show in a browser.

9. On the web interface, you can control the workflow by the buttons provided. In this example, if you click the Submit1 button, the workflow finishes.

10. Click to the UserXP button and browse this interface. Try to start a new workflow from this.

11. Create the following tasks:

• Download the application names: abstract task. • Show the applications: human task. • Buy the application: abstract task.

12. The Show the applications human task is not associated with an actor. Click the task and choose the Actors page. Next to the Actor Selectors box, click the Choose... button and select the Initiator. The Initiator is the role of the person who starts the task.

13. Let’s add some workflow variables to the process. Click the process and choose the Data page. Create the following variables:

• Applications: is the collection of names of the downloadable applications. The type of this variable is Text and the multiplicity is Multiple. • SelectedApplication: The user will select one of the available application. This Text variable with Single multiplicity contains the name of it.

27 Figure 5.3: The Hello task in the browser

Figure 5.4: The Browse Application process

28 Figure 5.5: The variables of the Browse Application process

14. Let’s create a script that substitutes the calling of other services. Select the Download the application names task and go to the Connectors page. Add a new script by selecting Scripting | Groovy – Execute a Groovy script.

15. Name the script instance to Get the applications, time it to the enter of the activity and hit next. At this window select the Edit expression... option from the combobox, and a conviniant Groovy editor will apear to write our script in it. This allows us to edit a Java-like expression or a method body where every flow variable is available.

Figure 5.6: The Groovy editor

16. Create this script that returns a collection of application name:

List applicationNames = new LinkedList() for (inti=0; i < 10; i++) { applicationNames.add("Application " + i) } return applicationNames

Click next and direct the result of this script to the applications variable and choose the REPLACE strategy.

17. Add a graphical view to the Show the applications task. There will be a section named All widget based on... that automatically derives the view from the checked flow variables. In this case we want to specify every element so unselect all. Drag a Radio buttons widget to the top of the view ad go to the data page of the property view. We would like to show the application names in this list, so got to the Avaible values and select the ${applications}...

29 option from the right side. As you select it a window should appear where you pick the “The whole list of values” option. We also want to put the name of the selected value to a variable, so edit that the ${field_Radio_buttons1} saves to selectedApplication.

Figure 5.7: The final properties of the radiobuttons.

18. The message of the Acknowledge action should refer to the selected variable, so let’s set it. If you closed the editor page go to the properties of the action select the Application page and edit the Hello task pageflow. At the Data page Hello world! message with an expression by the Edit expression... option and write that:

"Thank you for downloading the " + selectedApplication + " application."

19. Try to run the application. Don’t be afraid of the presettable variable at the begining.

20. Sone time an action may fail and the error should be handled. Add a script connector Buy the application action. Select the Throw error event at the If connector fails... options and name the error ot “failed”. The script should looks like this:

if(selectedApplication == applications.get(0)) throw new UnsupportedOperationException()

This script will fail with an exception if the user downloads the first application. The output should be neglected.

21. Add a Catch error item to the Buy the application action from the palette. Create a human task for the initiator and edit the control flow:

Figure 5.8: Error handling flow

Create a webpage for the task where there is a message that shows “Error in the web services!”.

30 22. Run the workflow and select the first application. It looks like that the workflow stops but eventually the next action arrives to the inbox.

Figure 5.9: The final process with exception handling

5.2 Complex workflow

We will implement a workflow for the actions of the user.

1. Create a new pool and name it to User workflow.

2. Create a start event, an end event and create the following tasks:

• Authenticate: service task • User action: human task • Login failed: human task • Browse applications: call activity • Upload application: abstract task • Logout: human task

For the human tasks, set the actor to Initiator.

3. Create a XOR gateway.

4. Time to create some variables:

• User ID: Integer • Username: Text • Password: Text

5. Also create a new variable named Action. To create an enumeration, set the Data type combobox to List of options.... Set the Name to UserActionType and add the following options:

• Browse • Upload • Logout

Click OK and Finish.

6. To create the login screen, click on the User workflow process. On the Application tab’s Entry Pageflow page add a new form named Login.

31 Figure 5.10: The UserActionType

Figure 5.11: The login screen

32 7. In the Add widgets based on... groupbox only select the username and password widgets.

8. Set the password field’s Field type to Password.

9. Connect the start event to the Authenticate task. This is a service task which simulates the authentication of the user. Add a new Groovy connector named Simulation of Authentication.

if (username == password) { return username.hashCode(); } else { return null; }

The result from connector’s output goes to the user_ID variable. Click Finish.

10. Depending on the authentication’s result, the user can proceed or fail the login. Create transitions from the Authenticate task to the User action task named success and the Login failed task name fail. 11. On the success transition choose Edit expression... in the Condition combobox and type user_ID != null. If this condition is not satisfied, the login fails. To implement this, tick the Default flow checkbox for the fail transition. 12. Add a form to the User action task. Only select the action widget, which will be mapped to radio buttons.

13. Now we have to create the conditions to the transitions from the XOR gateway. To do this, click on the transition and from the Condition combobox choose the Edit expression....

• For the transition to the Browse applications task, set the expression to action == UserActionType.Browse. Pay attention to import the enumeration – the Groovy editor is ba- sically and Eclipse editor, so you use the content assist (Ctrl+Space) to do so. • For the transition to the Upload application task, set the expression to action == UserActionType.Upload. • For the transition to the Logout task, tick the Default flow checkbox.

14. The user can browse and upload applications multiple times. To implement this in the process, we have to create a loop. In order to do so, create an abstract task named End of repeatable user action and create the necessary transitions (see the figure).

15. For the Browse applications task set the Subprocess Name to Browse_Application. 16. Create a form for the Logout task. Add a message saying The following user has logged out: ${username}. 17. Create a form for the Login failed task. Add a message saying Login failed. 18. From the Login failed and the Logout tasks draw a transition to the end event.

5.3 Tips

• If you close some windows by mistakes, you can make them reappear by choosing View | Reset view. • If you name a transition and then delete the name, Bonita will mark it as faulty with the following message: Empty name detected for a SequenceFlow. The solution is to name the transition. • Sometimes, the error markings don’t disappear until you manually validate the workflow by clicking Process | Validate.

33 Figure 5.12: The user action form

Figure 5.13: The final process

34 Chapter 6

Web services

6.1 Introduction

In this laboratory, we will create web applications. First, we will define the data types. We will create a JAX-WS and a JAX-RS web application and deploy them on a Tomcat server.

6.2 Remarks

For this laboratory, we relied heavily on the Vogella site’s (http://www.vogella.com/) tutorials. If you’re further interested in the topics, we recommend to study them – they are thorough and well-written.

• Servlet and JSP development with Eclipse WTP, http://www.vogella.com/articles/EclipseWTP/article.html • REST with Java (JAX-RS) using Jersey, http://www.vogella.com/articles/REST/article.html • Apache Tomcat, http://www.vogella.com/articles/ApacheTomcat/article.html • JAXB, http://www.vogella.com/articles/JAXB/article.html

6.3 Apache Tomcat

From Wikipedia (http://en.wikipedia.org/wiki/Apache_Tomcat): „Apache Tomcat is an open source web server and servlet container developed by the Apache Software Foundation. Tomcat implements the Java Servlet and the JavaServer Pages (JSP) specifications from Sun Microsystems, and provides a ,pure Java’ HTTP web server environment for Java code to run.”

Figure 6.1: The logo of Tomcat

35 6.4 WSDL

WSDL (Web Services Description Language)

• A developer using a bottom up method writes implementing classes first, and then uses a WSDL generating tool to expose methods from these classes as a Web service. This is simpler to develop but may be harder to maintain if the original classes are subject to frequent change. • A developer using a top down method writes the WSDL document first and then uses a code generating tool to produce the class skeleton, to be completed as necessary. This way is generally considered more difficult but can produce cleaner designs and is generally more resistant to change. As long as the message formats between sender and receiver do not change, changes in the sender and receiver themselves do not affect the web-service. The technique is also referred to as “contract first”.

6.5 JAX-RS

From Wikipedia (http://en.wikipedia.org/wiki/Java_API_for_RESTful_Web_Services): „JAX-RS: Java API for RESTful Web Services is a Java programming language API that provides support in creating web services according to the Representational State Transfer (REST) architectural style.”

6.5.1 Jersey

To use JAX-RS, we need to use Jersey (http://jersey.java.net/). „Jersey is Sun’s production quality reference implemen- tation for JSR 311: JAX-RS: The Java API for RESTful Web Services. Jersey implements support for the annotations defined in JSR-311, making it easy for developers to build RESTful web services with Java and the Java JVM.”

6.6 JAXB

From Wikipedia (http://en.wikipedia.org/wiki/Java_Architecture_for_XML_Binding): „Java Architecture for XML Binding (JAXB) allows Java developers to map Java classes to XML representations. JAXB provides two main features: the ability to marshal Java objects into XML and the inverse, i.e. to unmarshal XML back into Java objects.”

6.7 Maven

From Wikipedia (http://en.wikipedia.org/wiki/Apache_Maven): „Maven is a build automation tool used primarily for Java projects. Maven uses an XML file to describe the software project being built, its dependencies on other ex- ternal modules and components, the build order, directories, and required plug-ins. Maven dynamically downloads Java libraries and Maven plug-ins from one or more repositories such as the Maven 2 Central Repository, and stores them in a local cache. This local cache of downloaded artifacts can also be updated with artifacts created by local projects. Public repositories can also be updated.”

36 Chapter 7

Web services laboratory – step-by-step instructions

7.1 Prerequisites

To create a basic web service in Eclipse, you need to install some plug-ins.

7.1.1 Eclipse WTP

Eclipse provides a bunch of plug-ins called Web Tools Platform (WTP) to aid the development of web services.

1. Click Help | Install New Software. From the Work with combobox pick Juno. From the category “Web, XML, Java EE Development and OSGi Enterprise Development” install the following packages:

• Eclipse XML Editors and Tools – XML editor, highligher, etc. • JST Server Adapters Extensions – This is needed to connect to Apache Tomcat • Eclipse Java EE Developer Tools • Eclipse Java Web Developer Tools – These two are needed to create Dynamic Web Projects.

2. Restart Eclipse.

3. Click Window | Preferences. Pick Server | Runtime Environtment and click the Add... button.

4. Choose Apache | Apache Tomcat v7.0.

5. Click Next. Change the name to MDSD Tomcat. Click Download and install... and choose the installation location. Wait for the installation to complete: the Unknown version of Tomcat was specified. error message will disappear.

6. Click Finish.

7. Click OK.

37 Figure 7.1: An error message is displayed while installing Tomcat

Figure 7.2: After the installation is completed, the error message disappears

38 7.1.2 Maven

We will use Maven to resolve the Java dependencies of our software. To install Maven, install the m2e - Maven integration for Eclipse package from the Juno update site.

7.2 Datatypes

1. Create a Java project named hu.bme.mit.inf.appstore.data. 2. Create a package named hu.bme.mit.inf.appstore.data.model and add a class named Application.

public class Application { private int id; private String name; }

3. Add getter/setter methods to the class and generate a constructor that uses the name attribute as a parameter.

4. We will create a data provider for the model. Create a package named hu.bme.mit.inf.appstore.data.provider and add a class named ApplicationProvider.

package hu.bme.mit.inf.appstore.data.provider;

import hu.bme.mit.inf.appstore.data.model.Application;

import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map;

public enum ApplicationProvider { instance;

private Map map = new HashMap<>(); private int lastId =0;

public Application getApplication(int id) { return map.get(id); }

public List getApplications() { return new ArrayList<>(map.values()); }

public void insertApplication(Application application) { lastId++; application.setId(lastId); map.put(lastId, application); }

ApplicationProvider() { insertApplication(new Application("Flashlight")); insertApplication(new Application("Weather"));

39 } }

We implemented the Singleton pattern with an enumeration. See http://www.vogella.com/articles/ DesignPatternSingleton/article.html or Joshua Bloch’s book Effective Java for more details.

If you want to add use the Application class from an other project, go to the project Properties, Java Build Path. On the Projects tab click Add... and tick hu.bme.mit.inf.appstore.data.

7.3 JAX-WS

Further reading: http://wiki.eclipse.org/Creating_a_Bottom-Up_Java_Web_Service „The Java API for XML Web Services (JAX-WS) is a Java programming language API for creating web services.”

1. Create a new Dynamic Web Project called hu.bme.mit.inf.appstore.server.ws. When using the New Dynamic Web Project wizard, tick the Generate web.xml deployment descriptor checkbox. The web.xml file will be generated in the WebContent/WEB-INF directory. Remarks:

• If you forgot to generate the web.xml file, go to the Project Explorer, right click the project name and choose Java EE Tools | Generate deployment descriptor stub. • Unlike other natures (like the Plug-in Project and the Maven Project), the Dynamic Web Project nature cannot be added to the project from the – you have to start from a Dynamic Web Project and add other natures later.

2. Eclipse prompts if it should switch to the Java EE perspective: choose No.

3. Add a dependency to the hu.bme.mit.inf.appstore.data project (see the Datatypes section for more information).

4. Create a new package called hu.bme.mit.inf.appstore.server.ws and a new class called ApplicationManager:

package hu.bme.mit.inf.appstore.server.ws;

import java.util.List;

import hu.bme.mit.inf.appstore.data.model.Application; import hu.bme.mit.inf.appstore.data.provider.ApplicationProvider;

public class ApplicationManager {

public Application getApplication(int id) { return ApplicationProvider.instance.getApplication(id); }

public Application[] getApplications() { List list = ApplicationProvider.instance.getApplications(); Application[] array = list.toArray(new Application[list.size()]); return array; }

40 public void insertApplication(Application application) { ApplicationProvider.instance.insertApplication(application); } }

5. Right click the project and choose Web Services | Create Web Service. This will generate the description files and the client application, then deploy the application on the server.

• Web service type: Bottom up Java Bean Service • Service implementation: hu.bme.mit.inf.appstore.server.ws.ApplicationManager • Server level: Start service • Client type: Java proxy • Client level: Test client

Tick the Monitor the Web service checkbox. Go through the pages with the Next button and click Finish.

6. While deploying, you will get a warning that the Application class does not have a default no-arg contructor. Create a default constructor (a constructor with no arguments, hence often referred as no-arg constructor) to the Application class.

7. While deploying, Tomcat will throw the following exception: org.apache.axis.deployment.wsdd.WSDDNonFatalException: java.lang.ClassNotFoundException The reason is that the dependencies (i.e. the hu.bme.mit.inf.appstore.data project) are only available at compile time, but not avaiable at runtime. To correct this, go to the project’s Properties window, choose Deployment Assembly page. Click Add..., Project, hu.bme.mit.inf.appstore.data.

8. Use Create Web Service again and deploy the server.

9. Insert a new application with the insertApplication() method. The following XML envelope is generated:

3 News

10. List the application with the getApplications() method.

11. You can observe the traffic in the TCP/IP Monitor. To make the XML messages more readable, change Byte to Web Browser for both the Request and the Response messages.

41 Figure 7.3: The Web Service wizard

42 Figure 7.4: Inserting a new application to the application store

43 Figure 7.5: Listing the applications from the application store

44 7.4 JAX-RS

7.4.1 Creating the project

1. Create a new Dynamic Web Project called hu.bme.mit.inf.appstore.server.rest. When using the New Dynamic Web Project wizard, tick the Generate web.xml deployment descriptor checkbox. The web.xml file will be generated in the WebContent/WEB-INF directory. Set the Context root to appstore. 2. Eclipse prompts if it should switch to the Java EE perspective: choose No.

7.4.2 Dependencies

To use create REST services, we have to use Jersey. Jersey is the reference implementation for the JAX-RS specification.

1. We use Maven to resolve the dependencies. In order to use Maven, we need to add the Maven nature to the project. Right click the project and pick Configure | Convert to Maven Project. The default artifact settings are fine, click Finish.

2. Click the pom.xml file and choose the last tab, named pom.xml. To specify the dependencies, add the following code under the element:

com.sun.jersey jersey-server 1.17 com.sun.jersey jersey-bundle 1.17

7.4.3 Java code

1. Create a package named hu.bme.mit.inf.appstore.server.rest and a class named Hello.

package hu.bme.mit.inf.appstore.server.rest;

import javax.ws.rs.GET; import javax.ws.rs.Path;

@Path("hello") public class Hello {

@GET public String sayHello() { return "Hello"; }

}

45 7.4.4 Deployment

1. Edit the web.xml file in the WebContent/WEB-INF directory. Delete the content of the element and paste the following:

com.sun.jersey.spi.container.servlet.ServletContainer com.sun.jersey.config.property.packages 1

Fill the elements according to the following table:

display-name Application Store servlet-name (2×) Application Store REST Service param-value hu.bme.mit.inf.appstore.server.rest url-pattern /rest/*

2. Start the server. Tomcat will throw the following exception:

SEVERE: Servlet /hu.bme.mit.inf.appstore.server.rest threw load() exception java.lang.ClassNotFoundException: com.sun.jersey.spi.container.servlet.ServletContainer

The reason for this is that Eclipse not deploy dependencies (JAR files) resolved by Maven to the web application. To correct this, go to the project’s Properties window, choose Deployment Assembly page. Click Add..., Java Build Path Entries, Maven Dependencies. If you don’t use Maven, you have to put the JAR files to the WebContent/WEB-INF/lib directory and add them to the project’s build path.

3. Start the server. It will start but the browser in Eclipse will show a page with a 404 error. Let’s examine ho the URL of the REST service is built:

http://domain:port/context-root/url-pattern/path-from-REST-class

The context-root is defined in the org.eclipse.wst.common.component file, the url-pattern is de- fined in the web.xml file and the path-from-REST-class is defined in the Java source file. Remark: the Vogella JAX-RS tutorial is wrong on this point. The display-name in the web.xml file only sets the name of the application (which is shown in the Web Application Manager). It has nothing to do with the URL of the application. 4. If you want to change the context-root, go to the project Properties. On the Web Project Settings set the Context root. To check if it worked, go to the .settings directory and edit the org.eclipse.wst.common.component file.

46 Figure 7.6: Deployment Assembly

47

For now, leave the [deploy-name] and the [java-output-path] fields as they are.

5. If the server is running, stop it. Remove the application (right click, Remove) and restart the application. The URL’s context-root will be set to the new one. Remark: if this does not work as expected (e.g. the path in the Tomcat Web Application Manager is still the same), stop the server, run a clean operation (right click, Clean...) and start again.

7.5 JAXB

We will continue to work with the hu.bme.mit.inf.appstore.server.rest project and add JAXB support to it. This way, we send and receive Java objects serialized to XML.

1. Add a dependency to the hu.bme.mit.inf.appstore.data project (see the Datatypes section for more information).

2. Add the @XmlRootElement annotation to the Application class.

@XmlRootElement public class Application { // ... }

3. If you didn’t do so already, add a default constructor to the Application class. 4. Create a new class named ApplicationManager:

package hu.bme.mit.inf.appstore.server.rest;

import hu.bme.mit.inf.appstore.data.model.Application; import hu.bme.mit.inf.appstore.data.provider.ApplicationProvider;

import java.util.List;

import javax.ws.rs.Consumes; import javax.ws.rs.GET; import javax.ws.rs.POST; import javax.ws.rs.Path; import javax.ws.rs.PathParam; import javax.ws.rs.Produces; import javax.ws.rs.core.Context; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; import javax.ws.rs.core.UriInfo;

48 @Path("applicationmanager") public class ApplicationManager {

@Context private UriInfo uriInfo;

@GET @Path("list") @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON}) public List getApplications() { return ApplicationProvider.instance.getApplications(); }

@GET @Path("get/{id}") @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON}) public Application getApplication(@PathParam("id") int id) { Application application = ApplicationProvider.instance.getApplication(id); return application; }

@POST @Path("insert") @Consumes(MediaType.APPLICATION_XML) public Response insertApplication(Application application) { ApplicationProvider.instance.insertApplication(application); return Response.created(uriInfo.getAbsolutePath()).build(); }

}

7.6 Tomcat Web Application Manager

Tomcat has an administration page called Tomcat Web Application Manager. However, it will not work if Tomcat is launched with Eclipse’s default settings. To make it work, click the server in the Servers view. You have to change the Server Location from Use workspace metadata to Use Tomcat installation. If you have already started an application on the server, the radiobuttons will be disabled. To enable them stop the server (right click, Stop) and do a clean operation (right click, Clean...). After that, the radiobuttons should be enabled again.

Figure 7.7: If you have already deployed an application, the Server Location radiobuttons are disabled

49 Figure 7.8: Choose the Use Tomcat installation option

Start the server. Now you can access the Tomcat Web Application Manager on http://localhost:8080/manager/html. However, you can’t log in yet: you have to define a user. To do so, go to the Tomcat installation directory and add the following to the conf/tomcat-users.xml file’s element:

You should be able to login with the user admin and the password admin.

7.6.1 Performance monitoring

If you want to monitor the performance of Tomcat, you can use JConsole (http://docs.oracle.com/javase/7/docs/ technotes/guides/management/jconsole.html). JConsole can monitor applications that are compatible with Java Management Extensions (JMX) specification. You can find JConsole in your JDK’s bin directory. If you want to measure the performance of a web server, e.g. Apache Tomcat, you should use a performance testing tool like Apache JMeter (http://jmeter.apache.org/). JMeter is used in the Design for Dependability Laboratory Exercises (http://www.inf.mit.bme.hu/edu/courses/szbtlab) course of the „Dependable System Design” programme held in the autumn semester. Further reading:

• http://stackoverflow.com/questions/787070/how-to-properly-manage-tomcat-web-apps-inside-eclipse • http://stackoverflow.com/questions/6776421/display-the-tomcat-manager-application • http://stackoverflow.com/questions/2280064/tomcat-started-in-eclipse-but-unable-to-connect-to-link-to-http-localhost8085 • http://tomcat.apache.org/tomcat-7.0-doc/html-manager-howto.html

7.7 Testing a REST application

The simplicity of the REST style enables us to test REST applications without writing our own test client. Advanced Rest Client (http://chromerestclient.appspot.com/) is an extension for Google Chrome. Advanced Rest Client is capable of sending requests to REST applications with a specific HTTP method (e.g. GET, POST, etc.) and a header. This way, you can emulate the behaviour of a client application.

• http://localhost:8080/appstore/rest/applicationmanager/get/2, HTTP method: GET

• http://localhost:8080/appstore/rest/applicationmanager/insert, HTTP method: POST. Use the following payload:

50 Figure 7.9: The Tomcat Web Application Manager listing the appstore application

51 News

Create a Content-Type field in the header and set it to application/xml.

• http://localhost:8080/appstore/rest/applicationmanager/list, HTTP method: GET. Create an Accept field in the header and set it to application/json.

7.8 Google App Engine

From Wikipedia (http://en.wikipedia.org/wiki/Google_App_Engine): „Google App Engine is a platform as a service (PaaS) cloud for developing and hosting web applications in Google-managed data cen- ters. Applications are sandboxed and run across multiple servers. App Engine offers automatic scaling for web applications—as the number of requests increases for an application, App Engine automatically allocates more resources for the web application to handle the additional demand. Google App Engine is free up to a certain level of consumed resources.”

7.9 Tips and troubleshooting

• You can show the Show Servers view by clicking Window | Show View | Other... and choosing Server | Servers. • You can display the internal web browser by clicking Window | Show View | Other... and choosing General | Internal Web Browser. • If error are displayed because the javax packages cannot be found, right click on the project name, click Properties and look into Targeted Runtimes. It’s also worth trying to clean the project. • Sometime Maven does not download the dependencies and the project’s Maven Dependencies node is empty. Right click the project and choose Run As | Maven install. Because Maven depends on the accessibility of it’s main repository, this might not work for the first time: try again, it might does.

7.10 Additional materials

7.10.1 Creating a JSP Servlet

http://www.vogella.com/articles/EclipseWTP/article.html

1. Start Eclipse.

2. Click File | New | Other. Pick Web | Dynamic Web Project. Set the project name to hu.bme.mit.inf.helloworld. 3. Right click on the hu.bme.mit.inf.mdsd.helloworld project’s name: pick New | Other... and choose Web | Servlet. Set the Java package to hu.bme.mit.inf.helloworld and the Class name to HelloWorld.

4. While observing the possible settings, click Next, Next, Finish.

5. Add the following code to the doGet method in the HelloWorld class:

52 Figure 7.10: A POST operation with an XML payload on the application store

53 Figure 7.11: A GET operation on the application store returning JSON

54 protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setContentType("text/plain"); PrintWriter out = response.getWriter(); out.println("Hello world."); }

Choose Manually define a new server and set the Server runtime environment to the previously created MDSD Tomcat. Click Next and Finish. A browser tab will appear with the address http://localhost:8080/hu.bme.mit.inf.helloworld/HelloWorld and will display the following content (formatted as plain text):

Hello world.

6. Modify the code, e.g. change Hello world to Hello worlds. Eclipse will build the project automatically and deploy it on the Tomcat server. The Console view shows the following log:

INFO: Reloading Context with name [/hu.bme.mit.inf.helloworld] is completed

7. Refresh the browser’s page to see if it worked.

7.11 Sources

• Creating Bottom-Up Web Service, http://wiki.eclipse.org/Creating_a_Bottom-Up_Java_Web_Service • JSON and REST, The New Kids on the Data Block, http://www.slideshare.net/rmaclean/json-and-rest • Build a RESTful Web service using Jersey and Apache Tomcat: http://www.ibm.com/developerworks/library/ wa-aj-tomcat/

55 Chapter 8

Yakindu

From Wikipedia (http://en.wikipedia.org/wiki/YAKINDU_Statechart_Tools): Yakindu (http://statecharts.org/) Statechart Tools (SCT) is an open source tool for the specification and development of reactive, event-driven systems with the help of state machines. It consists of an easy-to-use tool for graphical editing and provides validation, simulation and code generators for different target platforms. The users come from both the industrial and academic sectors.”

Figure 8.1: The logo of Yakindu

Yakindu is developed by itemis, the same company that created Xtext.

Figure 8.2: The logo of itemis

8.1 Prerequisites

From the Yakindu update site, install the following plug-ins for Eclipse:

• Yakindu SCT 2 • Copy Paste Patch • YAKINDU SCT Generator C • YAKINDU SCT Generator Java • Yakindu Statechart Tools (SCT) 2 • Yakindu Statechart Tools (SCT) 2 SDK

56 8.2 Modeling

1. Create a new YAKINDU Xpand Generator Project.

2. Add a new YAKINDU Statechart Model.

3. Add the following code to the editor:

interface Service: in event request in event read var success : boolean

internal: event complete

4. Create the statechart #1 as shown on the figure.

Figure 8.3: Statechart #1

5. Run the statechart (Run As | YAKINDU Statechart) and experiment with the Simulation View.

6. Extend your statechart to #2 by adding a new State and a Choice. Keep in mind that the transitions have priorities, which may cause them to behave differently than expected. You can edit the Transition Priority in the Choice’s Properties view (Right click the Choice on the canvas and pick Show Properties View).

7. Extend your statechart to #3 by adding a new Composite State called Frontend.

8. Modify the statechart definition block to the following:

interface Service: in event request

57 Figure 8.4: Statechart #2

58 Figure 8.5: Statechart #3

59 in event read var success : boolean

internal: event complete event execute event finish

interface DB: in event access in event response var data: integer

9. Using the new events, extend your statechart to #4 by adding a new Composite State called Database.

Figure 8.6: Statechart #4

10. Modify your statechart to get #5 by adding a new Shallow History to the Frontend state.

8.3 Code generation

1. Add a generator by clicking File | New | Other... and picking Yakindu Statechart Generator Model. Name it service.sgen, choose YAKINDU SCT Java Code Generator and tick the service.sct statechart. 2. Modify the service.sgen file to the following:

60 Figure 8.7: Statechart #5

61 GeneratorModel for yakindu::java {

statechart service { feature Outlet { targetProject = "yakindu.labor" targetFolder = "src-gen" }

feature GeneralFeatures { TimerService = true } }

}

3. Add the src-gen folder to the Build Path. 4. Create a class named ServiceClient in the src folder in a package named service:

package service;

import org.yakindu.scr.TimerService; import org.yakindu.scr.service.ServiceStatemachine; import org.yakindu.scr.service.ServiceStatemachine.State;

public class ServiceClient {

public static void main(String[] args) throws InterruptedException { ServiceStatemachine sm = new ServiceStatemachine(); sm.setTimerService(new TimerService());

sm.enter();

sm.getSCIService().raiseRequest(); sm.runCycle();

if (sm.isStateActive(State.main_region_Frontend_r1_Read_request)) { System.out.println("Reading request."); } }

}

5. Run the program. It will produce the following output:

Reading request.

6. Create a method that runs a number of cycles, each of which sleeps for 0.2 seconds and then notifies the statechart.

private static void sleep(ServiceStatemachine sm, int limit) throws InterruptedException { for (inti=0; i < limit; i++) { Thread.sleep(200); sm.runCycle();

62 } }

7. Add the following call to the main method:

sm.getSCICommon().raiseExecute();

8. This will cause a compile-time error. The problem is that the execute event is internal, therefore the raiseExecute() method is private and cannot be accessed from the main method. To address this, create a new interfaced called Common for the the internal events.

interface Common: in event complete in event execute in event finish

9. Modify your statechart’s transitions accodingly to get statechart #6.

Figure 8.8: Statechart #6

10. After this, the raiseExecute() will be visible. Continue expanding the main method with the following:

sm.getSCICommon().raiseExecute(); // we added this previously

sm.getSCIDB().raiseAccess(); sm.runCycle();

63 sm.getSCICommon().raiseExecute(); sm.runCycle();

sleep(sm, 30);

sm.getSCIDB().raiseResponse(); sm.runCycle();

System.out.println("Data = " + sm.getSCIDB().getData());

sleep(sm, 10); sm.getSCICommon().raiseComplete(); sm.runCycle();

if (!sm.getSCIService().getSuccess()) { System.out.println("Unsuccessful call."); System.out.println("Recovery state active: "+ sm.isStateActive(State.main_region_Recovery) + "."); sleep(sm, 11); // more than 2 seconds }

if (sm.isStateActive(State.main_region_Responding)) { System.out.println("Responding."); }

sm.exit();

11. Run the application. The output is the following:

Reading request. Data = 6 Unsuccessful call. Recovery state active: true. Responding.

If you run the program multiple times, you can observe that the Data value is sometimes 5 instead of 6. Think about reason behind this.

8.4 Tips

• If the Java code is not generated automatically, right click the service.sgen file and click Generate State- chart Artifacts. • If you cannot find the Simulation View, right click the SC Simulation perspective’s name and choose Reset.

64 Chapter 9

Bonita

Source code snippets and URLs are available at https://svn.inf.mit.bme.hu/edu/trunk/mdsd/handout/public/ bonita_connector_materials/.

9.1 Introduction

1. Start the Bonita Studio and choose “MyProcessDiagram (1.0)” process.

2. We have changed the browse workflow a bit: it serve as an application collection that can be browsed or extended from various sources.

3. Start the workflow and inspect it: at this page the application available in our database should be displayed. Currently this list is empty.

4. There are buttons in the lower part of the page that shows the available options of extension sources. Those sources are services. Select the WebService option and go to the next page.

5. The New apps page displays the newly downloaded pages. Those applications will be inserted to the database. If you click next the first page will be displayed. At the end of the lecture this list will show the newly inserted applications too.

6. Choose None and end the workflow.

9.2 Scripting Reminder

1. At first substitute the web service with a script on “Update by web service”: ["New"].

2. This list should be directed to the newApplications variable, and replacing it.

9.3 Database Integration

1. Lets integrate our workflow with a MySQL database. Start the MySQL Workbench 5.2 CE.

2. Choose the SQL development section and select the Local MySQL database.

3. A dolphin in an aquarium will authenticate you: the password is root.

65 4. An SQL development environment will appear. We have created a database for the workflow: select the application table in the applications database, right click | Select Rows - Limit 1000.

5. The query and the result will appear with the single application called EvilStore. 6. Our applications will be saved to this table. This query will be copied to the workflow, so do not close it.

7. Select the Load the application names task and add a connector: Database | MySQL. Name it to ApplicationQuery and fill out the form as described in the picture below.

Figure 9.1: Bonita db connector configuration

8. Fill the Query field in the next page:

SELECT * FROM applications.application

9. Click Test configuration:

Figure 9.2: Bonita db test

10. Direct the values of the rowset to the Applications variable (java rowSet.getValues()). Select the replace strategy.

11. Now write the insert script in the “Save to DB” task. Add a new MySQL connector to the task, fill it in the same way.

66 12. Write the script as a return value of a method:

String ret = "INSERT INTO `applications`.`application` "+ "(`Name`) VALUES " boolean hasItem = false for(item in newApplications) { if(hasItem) ret+="," ret+="('"+item.replaceAll("[\\W]","")+" ')" hasItem = true } return ret

13. Test it with the evaluate button. The result will be (explain why):

INSERT INTO `applications`.`application` (`Name`) VALUES ('O'),('b'),('j'),('e'),('c'),('t')

14. Run the workflow, the result should be inserted to the table.

Figure 9.3: Bonita db test

9.4 Web services

You can start the Tomcat server with the start-tomcat.bat batch file on the Desktop. The C:\tomcat\webapps files are deployed On the Tomcat server, you have web applications available: a JAX-WS SOA web service and a JAX-RS REST web service. You have to web services available. Both offer the same functionality: they generate an arbitrary number of Application objects.

9.4.1 SOA web service

To test the SOA web service, start Google Chrome’s Advanced REST Client plug-in. Set the URL to http://localhost: 8080/appstore-ws/services/ApplicationManager and the HTTP method to POST. Add a header field SOAPAction (with an empty value) to the Headers. Paste the following code to the Payload field.

67 20

Notes: we can generate the SOA envelope with the Eclipse WTP platform. If you generate the client (as seen in the web service laboratory), you can observe the SOA envelope in the TCP/IP monitor.

SoapUI

SoapUI (http://www.soapui.org/) is capable of generating SOA envelopes from the WSDL file. Just create a New soapUI Project, add the ApplicationManager.wsdl WSDL file as Initial WSDL/WADL. Tick Create Request and click OK. The SOA envelope will be generated. http://www-inf.int-evry.fr/cours/WebServices/TP_Workflow/publish_news.html

9.4.2 REST web service

To observe the REST web service, simply visit http://localhost:8080/appstore-rest/rest/applicationmanager/ generate/20.

• Target NS: http://localhost:8080/appstore-ws/services/ApplicationManager • Service name: ApplicationManagerService • Port name: ApplicationManager • Request: same XML as above. • End point address: as above, http://localhost:8080/appstore-ws/services/ApplicationManager • Binding: http://schemas.xmlsoap.org/wsdl/soap/

Write the following code:

import javax.xml.transform.dom.DOMSource;

def output = (DOMSource) response def ret = [] def apps = output.getNode(). childNodes.item(0). childNodes.item(1). childNodes.item(0). childNodes

for(int i=0; i

9.5 Creating a new connector

1. Go to Connectors | New Connector, and name it to MyRestConnectorForApplications.

68 Figure 9.4: The SOA envelope can be observed in the TCP/IP monitor

69 Figure 9.5: SOA web service

70 Figure 9.6: SOA web service

2. Add an output parameter named result with List type.

3. Write the following Java code:

import java.util.ArrayList; import java.util.List;

import org.ow2.bonita.connector.core.ConnectorError; import org.ow2.bonita.connector.core.ProcessConnector;

public class MyRestConnectorForApplications extends ProcessConnector {

private ArrayList results;

@Override protected void executeConnector() throws Exception { results = new ArrayList(); results.add("A"); results.add("B"); }

@Override protected List validateValues() { // TODO Auto-generated method stub return null; }

/** * Getter for output argument 'result' * DO NOT REMOVE NOR RENAME THIS GETTER, * unless you also change the related entry in the XML descriptor file */ public java.util.ArrayList getResult() { return results; }

71 Figure 9.7: REST web service

72 Figure 9.8: Web Service Client dialog

73 }

4. Put it into the workflow, use replace strategy.

5. Edit the code to get the following:

import java.io.InputStream; import java.net.URL; import java.net.URLConnection; import java.util.ArrayList; import java.util.List;

import org.ow2.bonita.connector.core.ConnectorError; import org.ow2.bonita.connector.core.ProcessConnector;

import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory;

import org.w3c.dom.Document; import org.w3c.dom.Node; import org.w3c.dom.NodeList;

public class MyRestConnectorForApplications extends ProcessConnector {

private ArrayList results;

@Override protected void executeConnector() throws Exception {

URL url = new URL("http://localhost:8080/appstore-rest/rest/applicationmanager/generate/3"); URLConnection connection = url.openConnection(); Document document = parseXmlDom(connection.getInputStream());

results = new ArrayList(); NodeList apps = document.getElementsByTagName("applications").item(0).getChildNodes(); for(inti=0; i< apps.getLength(); i++) { results.add(apps.item(i).getTextContent()); } } public static Document parseXmlDom(InputStream is) {

Document document = null; try {

// getting the default implementation of DOM builder DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();

dbf.setValidating(false); dbf.setIgnoringComments(true); dbf.setIgnoringElementContentWhitespace(true); dbf.setNamespaceAware(true);

DocumentBuilder builder = dbf.newDocumentBuilder();

// parsing the XML file

74 document = builder.parse(is);

} catch (Exception e) { // catching all exceptions System.out.println(e.toString()); } return document; }

@Override protected List validateValues() { // TODO Auto-generated method stub return null; }

/** * Getter for output argument 'result' * DO NOT REMOVE NOR RENAME THIS GETTER, * unless you also change the related entry in the XML descriptor file */ public java.util.ArrayList getResult() { return results; } }

75 Chapter 10

Introduction to the Eclipse Modeling Framework

Author: Oszkár Semeráth

10.1 About the EMF

From Wikipedia (http://en.wikipedia.org/wiki/Eclipse_Modeling_Framework) „Eclipse Modeling Framework (EMF) is an Eclipse-based modeling framework and code generation facility for building tools and other applications based on a structured data model.” EMF’s data model is lightweight as it only defines a few but well-defined modeling elements. However, it has an extensive tooling support and community. For example, you can define the textual or graphical syntax of a language and generate the appropriate editors. EMF can generate Java code from the model with only a click of a button. The generated code is capable of serialisation to XMI and deserialisation from XMI files. EMF home page: http://www.eclipse.org/modeling/emf/

10.2 Description of the task

The goal of this exercise is to create the metamodel a customized Entity-Relationship Diagrams (ERD). Those diagrams can aid the development of software components that working with complex data structures. A later exercise will show you how can complete database schemes, full classes and the automated mapping between those can be derived from these documents. The following image presents an example of Entity Relation diagram.

10.3 Prerequisites

The Eclipse Modeling Tools edition contains every required plug-in.

10.4 Ecore model: step-by-step

1. Create a new Empty EMF Project by File | New | Other... | Eclipse Modeling Framework | Empty EMF Project. Name it to hu.bme.mit.mdsd.erdiagram.

76 Figure 10.1: Example of an Entity-Relationship diagram

2. There is a folder in the project named model. Create a new ECore Model in it by right click to the folder | New | Other. . . | ECore Model. Name it to ERDiagram.ecore.

3. A new editor opens that shows that the model resource has a yet unnamed empty package. Fill the missing properties in the property view:

• Ns Prefix: hu.bme.mit.mdsd.erdiagram • Ns URI: hu.bme.mit.mdsd.erdiagram

To show unavailable view go to Window | Show View | Other... | General.

4. It is possible to create the model in this tree editor but there is a more convenient editor for this purpose. Right click to the ecore file and choose the Initialize ECore diagram File... option. Name it to ERDia- gram.ecorediag.

5. Let’s make the following part:

Figure 10.2: A very simple Ecore model with two EClasses and an EReference between them

The features should be presented:

• EClass (with Is Abstract property) • EReference (with multiplicities and Is Containment) • Inheritance between the classes.

The objects of the instance models of the metamodel have to be in a tree hiearcy with respect of the composi- tion references. The editor can validate the model.

• Advanced Options: Direct editing for the properties of the elements of the model.

6. The result can be observed in the Outline view. Note that deleting from model and the diagram are different things. Create the metamodel of the Entity Relation Diagram on your own like it was a class diagram. A possible result is: The EOpposite feature should be presented.

77 Figure 10.3: The metamodel of the ER diagram

Figure 10.4: The metamodel completed with EAttributes

78 7. Adding attributes to the model. Showing the EEnum. The difference between the EAttribute and EReference is that the EAttribute is referring to an EDataTypes opposed to EReferences that endings to EClasses. The metamodel lacks of EOperations. The semantic of those is that they are functions over the model elements like refactoring. The EMF is a lightweight modelling tool with heavy support for data modelling, but little for operations. Instead of this use manager classes to write methods. At this phase we have all visible details of the Entity Relation Diagrams.

8. Adding namespace to the diagram, this could be the name of the diagram. The types of the attributes should be defined outside of the model, and referred by the diagram.

Figure 10.5: The model with the AttributeType class and the namespace attribute

9. The diagram may refer to an existing database with existing tables. The referred table and column names might be described in the diagram (for example the User entity is stored in the USER_TABLE because its name is reserved). Note the multiple inheritance at the Attribute entity.

10.5 Editor: step-by-step

This example shows how to generate classes and an editor from Ecore models.

1. The ecore files are the blueprints of the domain specific languages. To use the tooling support available in Eclipse some kind of Java class representation of those “boxes” are needed. Fortunately those classes can be automatically generated. Right click the ecore file and New | Other | Eclipse Modeling Framework | EMF Generator Model. The default ERDiagram.genmodel is fine. At the next step choose that the generator generate from an Ecore model. In the third step the URI of the Ecore model have to be added. Click on load and next. Choose the only avaliable package to generate and hit finish.

2. Another tree editor opens similar to the ecore editor. Browse some of the setting in the property editor. Right click to the root, and choose the Generate Model com- mand. Three package has been generated in the source folder. Browse for example the hu.bme.mit.mdsd.erdiagram/src/ERDiagram/EntityRelationDiagram.java file, and you can see that nothing strange has been generated. The implementation class has some unusual field, but the implementations of the functions of the interface are quite simple.

79 Figure 10.6: The model now supports the connection to databases

3. Generate an editor. Right click to the root of the genmodel file, and generate edit and editor in this order. 4. Right click to the project, and choose Run as | Eclipse application. 5. Create an empty project by File | New | Other... | General | Project and name it to Diagrams. 6. Create a new Entity Relation Diagram into the new project by right clicking on it and picking New | Other | Example EMF Model Creation Wizard | ERDiagram Model. The name can be the default My.erdiagram, and the model object (what we want to edit) should be Entity Relation Diagram. 7. Create the instance model. The editor is quite self-explanatory to use.

Figure 10.7: The tree editor for the Ecore model

10.6 Model manipulation: step-by-step

The following example shows how to edit the model from code.

1. Create a new Plug-in Project by right click | New | Plug-in Project. Name it to hu.bme.mit.mdsd.erdiagrammanipulator. 2. Add the following dependencies:

80 hu.bme.mit.mdsd.erdiagram The edited domain. org.eclipse.emf.ecore.xmi The instance model is serialised as an XMI document.

3. Create a class to the source folder:

package hu.bme.mit.jpadatamodelmanipulator name ModelEditor

4. Create an initialisation method for model loading.

public void init() { // For the initialisation of the model. // Without this the following error happens: // "Package with uri 'hu.bme.mit.mdsd.erdiagram' not found." ERDiagramPackage.eINSTANCE.eClass();

// Defining that the files with the .erdiagram extension should be parsed as an xmi. Resource.Factory.Registry reg = Resource.Factory.Registry.INSTANCE; reg.getExtensionToFactoryMap().put("erdiagram", new XMIResourceFactoryImpl()); }

5. The model is in an xmi file that can be generally handled as a resource. A resource can be referenced by an URI. Write a method that loads a resource:

public Resource getResourceFromURI(URI uri) { ResourceSet resSet = new ResourceSetImpl(); Resource resource = resSet.getResource(uri, true); return resource; }

6. The resource simply can be saved:

public void saveResource(Resource resource) { try { resource.save(Collections.EMPTY_MAP); } catch (IOException e) { System.out.println("The following error occured during saving the resource: " + e.getMessage()); } }

7. The content of the resource should be the ED diagram object.

public EntityRelationDiagram getModelFromResource(Resource resource) { // check the content! EntityRelationDiagram root = (EntityRelationDiagram) resource.getContents().get(0); return root; }

8. The ER diagram object should be edited through the interface and instantinated by the generated factory methods. This method creates a custom table data object for every entity that doesn’t already have one:

81 public void editDiagram(EntityRelationDiagram diagram) { for(Entity entity : diagram.getEntities()) { if(entity.getCustomTable() == null){ TableData tableData = ERDiagramFactory.eINSTANCE.createTableData(); tableData.setTableName(entity.getName().toUpperCase()+"_TABLE"); entity.setCustomTable(tableData); } } }

The result can be printed to the output by this method:

public void printTables(EntityRelationDiagram diagram) { for(Entity entity : diagram.getEntities()) { System.out.println(entity.getCustomTable().getTableName()); } }

9. You can get the URI by right click | Properties and copy the file to a string. For example my URI is:

URI uri = URI.createFileURI("C:/workspace/Diagrams/My.erdiagram");

The main method looks like:

public static void main(String[] args) { ModelEditor editor = new ModelEditor(); editor.init(); URI uri = URI.createFileURI("C:/workspace/Diagrams/My.erdiagram"); Resource resource = editor.getResourceFromURI(uri); EntityRelationDiagram diagram = editor.getModelFromResource(resource); editor.editDiagram(diagram); editor.printTables(diagram); editor.saveResource(resource); }

Right click to the class and choose Run as | Java Application. This will run our code as a simple Java application that loads modifes and saves a model.

10.7 Summary

At the end the following steps have been made: The final metamodel is:

10.8 General tips

• If anything goes wrong with the regeneration and there is problem with your code you have two options: – If the document was not edited by hand or it isn’t valuable delete it. Generate the code again, and it should be fine. It works on the Manifest.MF and the plugin.xml too. – In other case don’t be afraid of rewriting. For example if you delete an item from the metamodel the xmi that contains the instance model might have remaining tags with undefined type. That makes the xmi invalid, but it isn’t necessary to start over the instance model; simply delete the unwanted part from the code by hand.

82 Figure 10.8: The workflow of the laboratory and the dependencies between the artifacts (marked with dashed lines)

Figure 10.9: The final Ecore model

83 Chapter 11

Code generation technologies

11.1 JVM based languages

Summary: http://en.wikipedia.org/wiki/List_of_JVM_languages Beyond Java, many programming languages exist which are capable of producing software that can run on the Java Virtual Machine (JVM). These languages can usually feature close interoperability with Java libraries: call their methods and accept their calls. In recent years, the TIOBE index (http://www.tiobe.com/index.php/content/paperinfo/tpci/index.html), which shows the popularity of programming languages put Java in the top two positions, while Scala, Groovy and Clojure was in the top 100.

11.1.1 Scala

Home page: http://www.scala-lang.org/ Like Java, Scala is strongly object-oriented and statically typed but also uses elements from functional programming. Scala natively supports building concurrent applications.

Figure 11.1: The logo of Scala

11.1.2 Groovy

Home page: http://groovy.codehaus.org/ Groovy is a script-like language with functional elements. Most syntactically correct Java code is also a corrent Groovy code. Groovy supports both static and dynamis typing. Remark: in Bonita (http://www.bonitasoft.com/), used on the Service Integration course, you can specify expres- sions in Groovy (http://www.bonitasoft.com/resources/documentation/groovy).

84 Figure 11.2: The logo of Groovy

11.1.3 Clojure

Home page: http://clojure.org/ Clojure is a dialect of the Lisp programming language. Software created in Clojure can be compiled to run on the JVM, the .NET Common Language Runtime (CLR) or a JavaScript engine. Clojure is a functional language which strongly support building concurrent applications.

Figure 11.3: The logo of Clojure

11.2 Code generation with Eclipse technologies

11.2.1 Xtext

Home page: http://www.eclipse.org/Xtext/ Xtext is a framework creating programming languages and domain-specific languages. Xtext is capable of generating the parser the interpreter and provide Eclipse IDE support for the language. The developers task is to define language’s grammar in .xtext files (http://www.eclipse.org/Xtext/documentation.html#_1). Xtext’s components build on the Eclipse Modeling Framework (EMF), so Xtext development can be easily integrated with other EMF based technologies (e.g. GMF).

Figure 11.4: The logo of Xtext

11.2.2 Xbase

Home page: http://wiki.eclipse.org/Xbase Xbase is partial programming language. It’s purpose is to serve as a basis of the expessions in the programming languages generated by Xtext. Xbase expressions closely resemble Java expressions: the mutual elements include strings, if and foreach structures, method invocations, constructors, etc.

85 The target platform of Xbase expressions is the JVM. At first, Xbase generates Java code and later compiles it to byte code. Xbase is statically typed. It’s features include closures and operator overloading. It provides convenient type inference mechanism and a switch structure more advanced than Java’s (see the Xbase home page above). Remark: the check expression in IncQuery patterns (http://viatra.inf.mit.bme.hu/incquery) are written in Xbase.

Figure 11.5: The logo of Xbase

11.2.3 Xpand

Home page: http://www.eclipse.org/modeling/m2t/?project=xpand, http://wiki.eclipse.org/Xpand Xpand is a highly specialised language, with the purpose of generating code from EMF models. Xpand is statically typed and support polymorphic template invocation, aspect-oriented programming (AOP), model transformation, model validation, etc. Example code: http://www.openarchitectureware.org/pub/documentation/4.3.1/html/contents/emf_tutorial. html#emf_tutorial_generating_code

Xtend (deprecated)

Home page: http://wiki.eclipse.org/Xpand/Galileo See also: http://dslmeinte.wordpress.com/2011/09/19/using-xtexts-xtend2-language/ Originally, Xtend was a sublanguage of Xpand (file with .ext and .xpt extension). It was capable of supporting functional programming elements. Remark: Xpand and its Xtend technologies are no longer actively developed, so we don’t use it in the courses.

11.2.4 Xtend (previously called Xtend2)

Home page: http://www.eclipse.org/xtend/ Blog post: http://blog.efftinge.de/2010/12/xtend-2-successor-to-xpand.html Wikipedia: http://en.wikipedia.org/wiki/Xtend_(programming_language) Xtend2 was created with the intent to replace Xpand and Xtend. Later the number „2’‘was dropped from its name. Hence, when we use the term „Xtend” we refer to the new technology. In order to be distinguishable, the files created with the newer Xtend technology have the extension .xtend. Xtend is a JVM based language. It’s grammar and editor was created with Xtext. The language uses Xbase expressions. Xtend is statically typed, and uses both object-oriented and functional elements – e.g. lambda expressions. Xtend can cover the whole process of generating code from an EMF model, including the definition of the templates and imperative code that executes the process.

86 Figure 11.6: The logo of Xtend

87 Chapter 12

JPA

This tutorial shows a simple example that covers most of the JPA technology.

1. Create a new java project with the name hu.bme.mit.mdsd.jpaexample.

2. Create a new package to the src folder and name it to car.entities.handwritten. 3. Create a class named Dealer:

public class Dealer { private String name; private List productRange = new ArrayList(); }

4. And a one named Producer:

public class Producer { private String name; private List worksWith = new ArrayList(); }

5. Generate the getters and setters.

6. To persist the instances to a database some jar file is needed:

• javax.persistence_2.0.4.jar: The java persistence API itself. • eclipselink.jar: The way of object-relational mapping is defined in this jar. We use Eclipse link at this lecture. • mysql-connector-java-5.1.22-bin.jar: The database driver. In this case the application is connected to a MySQL database.

Those jar files can be downloaded from the site of the vendor.

7. Those files should be added to the project. Previously the Maven tool is used for this purpose, but at this case they will be added manually. Create a new folder to the project and call it to lib. Put the files to this folder by drag and drop them.

8. Those files should be added to the classpath of the project. To do this right click to the project and choose Build Path | Configure Build Path. Add the jars to the build path with the Add JARs button at the Lybraries menu.

88 9. Some configuration is inevitable. Create a META-INF folder into the project and add a file into it named persistence.xml. The content:

false

This configuration defines the following properties:

• A name for the persistence-unit • Username / Password for the database • The path of the database as a URL • What should happen if there is an existing table with the same name (possibly from a previous version). Another possibility that resets the tables is drop-and-create-tables. • Which class should be persisted?

10. Annote the persistent classes. Add @Entity, the @Table(name="Producer_Table") and the @Table(name="Dealer_Table") annotation to the respective persistent classes.

11. An ID field is necessarry to every class:

@Id @GeneratedValue(strategy=GenerationType.TABLE) @Column(name="ID") private int id;

public int getId() { return this.id; }

The manually defined column name and the generation strategy should be inspected.

12. Create a new class named FillDatabase_1 and add a main method:

public static void main(String[] args) { EntityManagerFactory factory = Persistence.createEntityManagerFactory("cars"); EntityManager em = factory.createEntityManager();

em.getTransaction().begin();

Producer

89 producer1 = new Producer(), producer2 = new Producer(), producer3 = new Producer(); producer1.setName("Producer 1"); producer2.setName("Producer 2"); producer3.setName("Producer 3");

em.persist(producer1); em.persist(producer2); em.persist(producer3);

em.getTransaction().commit();

em.close(); }

13. Start the MySQL workbench and check the database named test.

14. Run the application, and check the console output.

15. Check the database: new tables have been created, and there is one that contains the producers.

Figure 12.1: The result of the first persist

16. To link the dealers with the producers a new manager class is defined:

public class CarManager { public void linkDealerToProducer(Dealer dealer, Producer producer) { dealer.getProductRange().add(producer); producer.getWorksWith().add(dealer); } }

17. Define the Many To Many relation in Producer:

@ManyToMany @JoinTable( name="DealerProducerJoin", joinColumns={@JoinColumn(name="ProductID",referencedColumnName="ID")}, inverseJoinColumns={@JoinColumn(name="DealerID", referencedColumnName="ID")}) private List worksWith = new ArrayList();

And in Dealer:

@ManyToMany(mappedBy="worksWith") private List productRange = new ArrayList();

18. Fill the database with dealers too:

90 //... producer3.setName("Producer 3");

Dealer dealer1 = new Dealer(), dealer2 = new Dealer(), dealer3 = new Dealer(); dealer1.setName("Even dealer"); dealer2.setName("Odd dealer"); dealer3.setName("Prime dealer");

CarManager manager = new CarManager();

manager.linkDealerToProducer(dealer1, producer2); manager.linkDealerToProducer(dealer2, producer1); manager.linkDealerToProducer(dealer2, producer3); manager.linkDealerToProducer(dealer3, producer2); manager.linkDealerToProducer(dealer3, producer3);

em.persist(producer1); //...

19. If you run it a java.lang.IllegalStateException exception will appear: During synchronization a new object was found through a relationship that was not marked cascade PERSIST. The first solution is to persist the dealers too:

em.persist(dealer1); em.persist(dealer2); em.persist(dealer3);

20. The second is that if it is defined if the products are persisted the dealers should also be persisted:

@ManyToMany(cascade=CascadeType.ALL)

We use this one.

21. If the application is executed the tables of the database will be filled.

22. Create an application that queries the database:

public class DataBaseQuery {

/** * @param args */ public static void main(String[] args) { EntityManagerFactory factory = Persistence.createEntityManagerFactory("cars"); EntityManager em = factory.createEntityManager();

Query q1 = em.createQuery("select p from Producer p"); @SuppressWarnings("unchecked") List producers = q1.getResultList();

for (Producer producer : producers) { System.out.println(producer.getId() +"-" + producer.getName()); for (Dealer dealer : producer.getWorksWith()) {

91 System.out.println("-" +dealer.getName()); } }

em.close(); } }

23. If you execute this the result will be empty, so set the ddl-generation value in the persistence.xml to create- tables

24. The query can be parameterised like this:

"select p from Producer p where p.id = 1"

92 Chapter 13

Code generation laboratory

1. Open the hu.bme.mit.mdsd.erdiagram project, and generate the model, the edit and the editor as usual.

2. Check the handed out code: the hu.bme.mit.mdsd.generatebutton and the hu.bme.mit.mdsd.codegenerator. This project contains an extension that puts a button to the cool bar. The button is detailed in the Technical basics lecture. Our goal is to initiate the code generation procedure with this button.

3. The event handler of the button is implemented in the execute method of the JPADataGenerateCommandHandler class. The method structured like this:

• IWorkbenchWindow window: Getting the actually edited active workbench. • ISelection selection: Checks it if there is anything selected. • Object firstElement: Only a single element should be selected. • EntityRelationDiagram dataModel: This element should be an ER diagram. • System.out.println(dataModel.eResource().getURI()): The result should be printed to the console of the host eclipse.

If the method fails in those steps it will show an error message. This event handler gets a diagram that we can generate from.

4. Run the plug-ins in an eclipse application.

5. Import the JPAExample project to the runtime eclipse and check My.erdiagram.

6. Select the diagram model element and press the ERDiagram -> Code button. If you push the button while an ER diagram is selected the URL of the model should be printed to the output.

7. From this we work in the hu.bme.mit.mdsd.codegenerator project. There is a support class named GeneratorHelper in this project that will be used for the code generation. The following method creates a java file into the project that the parameter model nextTo is in. The file is placed into the source folder named src, which is expected to be exist. It creates the folder composition from the namespace hierarchy, so for example the namespace hu.bme.mit.jpadatagenerator.helper creates the src/hu/bme/mit/jpadatagenerator/helper folder if it isn’t existed previously. The java file named .java will be placed into this folder with the content defined by the content parameter, where comes from the parameter name. The method only replaces a derived file and creates a derived file.

public static IFile createJavaFile(Resource nextTo, String namespace, String name, Boolean derived, CharSequence content)

93 8. Create a new package named hu.bme.mit.jpadatagenerator.templates to the hu.bme.mit.mdsd.codegenerator project and create an XTend class named JPAProjectGenerator by Right click to the package | New | Other | Xtend | Xtend Class.

9. Fill out with the class with an initial implementation that prints the entities of the ER diagram:

class JPAProjectGenerator { def generateDataModel(EntityRelationDiagram dataModel) { for(clazz : dataModel.entities){ System::out.println(clazz.name) } } }

Some feature of the language should be emphasized:

• The Xtend class equivalent with the java class. • An Xtend class may contains some method defined by the def. • The method has a usual java-like explicitly typed parameterlist. • The method doesn’t have return type defined, but if you put the cursor over the definition the hover says: void generateDataModel(EntityRelationDiagram dataModel) So the return value is strongly typed, but the return type is inferred from the method body. • The previous point applies to the loop variable clazz, which is inferred to be an Entity. • A static field is accessible with the scope operator ::. • The ; character from the end of the lines are omittable.

10. If you save this a source folder named xtend-gen will be created. This contains the JPAProjectGenerator java class that is equivalent with the xtend one.

11. Fill the Xtend class. It calls the helper class to create the java files with the content Hello world!

def generateDataModel(EntityRelationDiagram dataModel) { for(clazz : dataModel.entities){ GeneratorHelper::createJavaFile( dataModel.eResource, dataModel.namespace, clazz.name, true, '''Hello world!''') } }

Save it and write the JPADataGenerateCommandHandler class to call the generateDataModel method:

//System.out.println(dataModel.eResource().getURI()); JPAProjectGenerator generator = new JPAProjectGenerator(); generator.generateDataModel(dataModel);

Lessons from the examples:

• You can call the Xtend code from java (like generator.generateDataModel(dataModel)). • You can call the java code from Xtend (like GeneratorHelper::createJavaFile). • A field can be easily accessed like it would be an attribute (or C# property), without calling theget/set method. Of course this is only a syntactic sugar.

94 • The ”’Hello world!”’ expression returns a CharSequence with the content. This is similar to the expression "Hello world!" with the typeString.

12. From now on only the template will be edited. At first we create some simple method. A Relation‘ has twoRelationEnding“. It is useful if the opposite of an ending is accessable:

def otherEnding(RelationEnding ending) { // If ending is the left end of the relation return with the right ending. if(ending.leftEndingOf!=null){ return ending.leftEndingOf.rightEnding; } // Otherwise return with the right ending. else return ending.rightEndingOf.leftEnding; }

A feature of the Xtend language is the application of the extension methods. You can use the first parameter as the host of the extension, like:

ending.otherEnding == otherEnding(ending)

This could be very conviniant. From now we use the .compile method to generate the code from a model element.

13. This example demonstrates the use of lambda expressions. Create the following method. The comments show the results of subexpressions:

def references(Entity entity) { // Lambda help: // // | The collection of the endings that targets this entity. // | | We want to get another collection by changing every elements // | | of the original collection. // | | | This is a function that tells how to change every // | | | elements. In this case this function returns the // | | | opposing pair of the edge. // | | | | We need only some of the element in this // | | | | collection // | | | | | This functions tells which element // | | | | | is needed. // | | | | | In this case this getter function // V V V V V returns that the ending is navigable. entity.referredBy.map[otherEnding].filter[navigable] }

14. If you create big CharSequence block, you can insert code in it with the «» characters. Those characters can be summoned by the content assist. This can be used to create control commands like FOR or IF too. An example:

«FOR attribute : entity.attributes SEPARATOR"\n"» private «attribute.type.name» «attribute.name»; «ENDFOR»

95 Chapter 14

NoSQL

Figure 14.1: The logo of Neo4j

14.1 Neo4j console

Neo4j provides an online REPL (read–evaluate–print loop) console at http://console.neo4j.org/ to experiment with Cypher. A preloaded graph database is available at http://console.neo4j.org/r/39s1je.

• Delete root node if necessary.

START n=node(0) DELETE n

• Get all subjects.

START n=node(*) RETURN n

• Subjects with at least 4 credits that have an exam.

START n=node(*) WHERE n.credits >= 4 AND n.exam = true RETURN n

• Subjects that are required to complete before some other subject.

START n=node(*) MATCH n-[r:ALAIRASRA_EPUL]->() WHERE n.credits >= 4 AND n.exam = true RETURN DISTINCT n

96 Warning: don’t forget the colon.

• Subjects that are not required to complete before any other subject.

START n=node(*) MATCH n-[r?:ALAIRASRA_EPUL]->() WHERE n.credits >= 4 AND n.exam = true AND r IS NULL RETURN DISTINCT n, r

• Subjects that are required to complete before an other subject, which can be taken simultaneously with some a third one.

START n=nodes*) MATCH n-[r:ALAIRASRA_EPUL]->m-[s:EGYUTT_VEHETO_FEL]s>o RETURN n, r, m, s, o

• The query is equivalent to:

START n=node(*) MATCH n-[r:ALAIRASRA_EPUL]->m, m-[s:EGYUTT_VEHETO_FEL]->o RETURN n, r, m, s, o

14.2 Embedded mode

Create a new Maven Project in Eclipse. Select Simple project (no archetype).

• Group Id: etr.neo4j • Artifact Id: etr.neo4j.embedded

14.2.1 Dependencies

Go to Neo4j’s homepage (http://www.neo4j.org/) and naviagte to Download | Maven dependency. Add the following dependency to the pom.xml with the version set to 1.8.2.

org.neo4j neo4j 1.8.2

14.2.2 Java code

Tips:

• Preferences | Java | Editor | Typing | Automatically insert at correct position | Semicolons. • Use Extract to local variable refactor.

Create two classes in a package called embedded. The Main class:

97 Figure 14.2: The online console of Neo4j

98 package embedded;

public class Main { public static void main(String[] args) { Neo4jHandler neo4jHandler = new Neo4jHandler(); neo4jHandler.run(); } }

The Neo4jHandler class:

package embedded;

import java.io.File; import java.io.IOException; import java.util.Map;

import org.neo4j.cypher.javacompat.ExecutionEngine; import org.neo4j.cypher.javacompat.ExecutionResult; import org.neo4j.graphdb.GraphDatabaseService; import org.neo4j.graphdb.Node; import org.neo4j.graphdb.RelationshipType; import org.neo4j.graphdb.Transaction; import org.neo4j.graphdb.factory.GraphDatabaseFactory; import org.neo4j.graphdb.index.Index; import org.neo4j.graphdb.index.IndexManager; import org.neo4j.kernel.impl.util.FileUtils;

public class Neo4jHandler {

public void run() { String path = "neo4j-db";

File file = new File(path); if (file.exists()) { try { FileUtils.deleteRecursively(file); } catch (IOException e) { e.printStackTrace(); } }

GraphDatabaseService graphDb = new GraphDatabaseFactory() .newEmbeddedDatabase(path); IndexManager index = graphDb.index(); Index index_names = index.forNodes("__names__");

Transaction tx = graphDb.beginTx(); try { Node fiz1 = graphDb.createNode(); fiz1.setProperty("name", "Fizika 1."); fiz1.setProperty("credits",4); index_names.add(fiz1, "name", "Fizika 1.");

99 Node fiz2 = graphDb.createNode(); fiz2.setProperty("name", "Fizika 2."); fiz2.setProperty("credits",4); index_names.add(fiz2, "name", "Fizika 2.");

fiz1.createRelationshipTo(fiz2, EtrRelationship.VIZSGARA_EPUL);

tx.success(); } finally { tx.finish(); } }

enum EtrRelationship implements RelationshipType { VIZSGARA_EPUL, KREDITRE_EPUL, EGYUTT_VEHETO_FEL }

}

14.2.3 Neoclipse

Run Neoclipse (https://github.com/neo4j/neoclipse), create a new database connection to the neo4j-db directory. To test the application, run the following Cypher query in Neoclipse:

START n=node:__names__(name='Fizika 1.') RETURN n.name, n.credits

14.2.4 Cypher query from Java

Add the Cypher query to the Java code. Warning: use the javacompat execution engine/result.

ExecutionEngine engine = new ExecutionEngine(graphDb); String query = "START n=node:__names__(name='Fizika 1.')\r\n" + "RETURN n.name, n.credits"; ExecutionResult result = engine.execute(query);

for (Map row : result) { System.out.println(row); }

Tip for inserting Cypher queries to Java: go to Preferences | Java | Editor | Typing and tick Escape text when pasting into a string literal. To create the whole database, run the Cypher query from https://svn.inf.mit.bme.hu/edu/trunk/mdsd/handout/ public/nosql_materials/elotanulmanyi_rend_cypher_ekezetes.txt Eclipse will prompt to change the encoding of the file: choose UTF-8. Tip: autocomment with Ctrl + 7 or Ctrl + Shift + C.

100 14.3 Server mode

Run the server with C:\neo4j-community-1.8.2\bin\Neo4j.bat. If you get the error Unable to access jarfile C:\NEO4J-~1.2\bin\windows-service-wrapper-*.jar, you ran into the issue mentioned at https://github.com/neo4j/neo4j/issues/391. To solve it, edit base.bat: change set wrapperJarFilename=windows-service-wrapper-*.jar to set wrapperJarFilename=windows-service-wrapper-4.jar

14.3.1 Using the REST API manually

Use the Advanced Rest Client to access the Neo4j server.

• URL: http://localhost:7474/db/data/cypher • HTTP Method: POST • Headers: Accept: application/json

The payload to the creation query is in the https://svn.inf.mit.bme.hu/edu/trunk/mdsd/handout/public/nosql_ materials/rest_create_query.txt file. Query all nodes with:

{ "query": "START n=node(*) RETURN n", "params":{ } }

Observe how verbose the output is. Try the following query:

{ "query": "START n=node(*) RETURN n.name, n.credits", "params":{ } }

Warning: this is not going to work if the root node still exists. Delete it with:

{ "query": "START n=node(0) DELETE n", "params": {} }

Run the previous Cypher query and observe how compact it’s output is.

14.3.2 Web administration interface

You can access the web administration interface: http://localhost:7474/webadmin/. Observe the dashboard and play with the data browser.

101 Figure 14.3: Visualisation settings in the Data browser

Figure 14.4: Visualisation of the graph in the Data browser

102 14.3.3 REST API in Java

Create a Maven project in Eclipse.

• Group Id: etr.neo4j • Artifact Id: etr.neo4j.embedded

Luckily, we have a great wrapper to use (https://github.com/neo4j/java-rest-binding), but it is not available in the Maven Central Repository.

Installing Maven

To install Maven, download from it http://maven.apache.org/download.cgi and follow the Installation Instructions. In Windows, go to the System window (Windows + Break), click Advanced system settings | Environment vari- ables... | System variables. Set the following variables:

• M2_HOME = c:\apache-maven-3.0.5 • M2 = %M2_HOME%\bin • Path = ;%M2%

Use mvn --version to test if it works. In Debian-based Linux distributions, simply install with:

sudo apt-get install maven

Note that the maven package contains Maven 3 and the maven2 package contains Maven 2. You need the former.

Compiling the Neo4j java-rest-binding project with Maven

Retrieve the java-rest-binding project for Neo4j 1.8.

• The simple way: download https://svn.inf.mit.bme.hu/edu/trunk/mdsd/handout/public/nosql_materials/ java-rest-binding-1.8.1.zip and unzip.

• The more adventurous way: clone the repository from GitHub:

git clone git://github.com/neo4j/java-rest-binding.git

Open a command line, navigate to the java-rest-binding directory. Switch to the 1.8.1 branch (note that the semantics of the git checkout command are different of the svn checkout command).

git checkout 1.8.1

Compile and install the project with the following command:

mvn clean install

If this fails, you may try the following:

103 mvn clean install -DskipTests

Use the dependency provided in the GitHub project’s README.md file, but correct the version number to 1.8.2:

org.neo4j neo4j-rest-graphdb 1.8.2

Creating the Java application

Create a package called client and create the following classes: The Main class:

package client;

public class Main {

public static void main(String[] args) { Neo4jClient neo4jClient = new Neo4jClient(); neo4jClient.run(); }

}

The Neo4jClient class:

package client;

import java.util.Collection; import java.util.Map;

import org.neo4j.helpers.collection.IteratorUtil; import org.neo4j.helpers.collection.MapUtil; import org.neo4j.rest.graphdb.RestAPI; import org.neo4j.rest.graphdb.RestAPIFacade; import org.neo4j.rest.graphdb.query.RestCypherQueryEngine; import org.neo4j.rest.graphdb.util.QueryResult;

public class Neo4jClient {

String serverUrl = "http://localhost:7474/db/data"; RestAPI restApi = new RestAPIFacade(serverUrl);

public void run() { RestCypherQueryEngine queryEngine = new RestCypherQueryEngine(restApi); String query = "START n=node(*) RETURN n.name AS name, n.credits AS credits"; QueryResult> queryResult = queryEngine.query(query, MapUtil.map()); Collection> result = IteratorUtil.asCollection(queryResult);

104 for (Map map : result) { String name = (String) map.get("name"); Integer credits = (Integer) map.get("credits"); System.out.println(String.format( "%s(%d credits)", name, credits)); }

restApi.close(); }

}

This will run the Cypher query through the REST API, and list the names and credit numbers of the subjects.

105 Chapter 15

IncQuery

Figure 15.1: The logo of EMF-IncQuery

15.1 Setup

1. Import the project from start.zip. 2. Generate the model, the edit and the editor from the genmodel file in the model folder of the hu.bme.mit.mdsd.erdiagram project.

3. Run as Eclipse Application.

4. Import the ERDiagramExample to the runtime Eclipse and check the instance model. 5. Create a new IncQuery project and name it to hu.bme.mit.mdsd.erdiagram.queries. 6. Create a new query definition in a package named hu.bme.mit.mdsd.erdiagram and a file named queries.eiq. In the wizard create an empty query. Fill the first query:

106 package hu.bme.mit.mdsd.erdiagram

import "hu.bme.mit.mdsd.erdiagram"

pattern entityWithName(entity, name) { Entity.Name(entity,name); }

7. Load the query and the instance model to the Query Explorer.

15.2 Simple Query Language Tutorial

1. Structure your source code to 4 blocks like this:

//------// Support //------

//------// Visualize //------

//------// Validate //------

//------// Derived //------

Every pattern goes to one of those categories. The entityWithName goes to Support. 2. Create a query to the Validate that checks if the name of a NamedElement is only an empty string:

pattern emptyNamedElement(element: NamedElement) { NamedElement.Name(element,""); }

3. Create a query to the Validate that checks if two entity has the same name:

pattern sameNamedEntities(entity1, entity2, commonName) { Entity.Name(entity1, commonName); Entity.Name(entity2, commonName); entity1!=entity2; }

4. Create a query to the Validate that checks if the name starts with a noncapital letter:

pattern entityStartsWithSmallCase(entity) { Entity.Name(entity,name); check( !name.matches("^[A-Z].+") ); }

107 5. Create a query to the Derived that gets the other endign of a relation ending:

pattern other(ending:RelationEnding, other) { Relation.leftEnding(relation, ending); Relation.rightEnding(relation, other); } or { Relation.rightEnding(relation, ending); Relation.leftEnding(relation, other); }

6. Create a query to the Visualize that summarizes this three validation condition:

pattern badEntity(entity, name) { find sameNamedEntities(entity, _other, name); } or { Entity.Name(entity, name); find emptyNamedElement(entity); } or { Entity.Name(entity, name); find entityStartsWithSmallCase(entity); }

7. Create a query to the Visualize that matches to the well-named entities:

pattern goodEntity(entity, name) { Entity.Name(entity, name); neg find badEntity(entity,_); }

8. Create a query to the Visualize that gets the attributes:

pattern attribute(entity, attribute) { Entity.attributes(entity,attribute); }

9. Create a query to the Visualize that gets the attributes:

pattern attribute(entity, attribute) { Entity.attributes(entity,attribute); }

10. Create a query to the Visualize that gets relations:

pattern relation(entity1, entity2) { Relation.leftEnding.target(relation, entity1); Relation.rightEnding.target(relation,entity2); }

11. Create a query to the Visualize that matches on the attributes and check the properties:

pattern attributeWithName(attribute, name, type, key){ Attribute.Name(attribute,name); Attribute.type.Name(attribute,type); Attribute.isKey(attribute,true); key=="[k]"; } or { Attribute.Name(attribute,name);

108 Attribute.type.Name(attribute,type); Attribute.isKey(attribute,false); key==""; }

15.3 Visualization tutorial

1. Use the visualize block to create a view. Annote the patterns:

@Item(item = entity, label = "$name$") pattern goodEntity(entity, name)

@Item(item = entity, label = "$name$") @Format(color = "#ff0000") pattern badEntity(entity, name)

@Item(item = attribute, label = "$key$$name$: $type$") @Format(color = "#00ffff") pattern attributeWithName(attribute, name, type, key)

@Edge(source = entity, target = attribute) pattern attribute(entity, attribute)

@Edge(source = entity1, target = entity2) pattern relation(entity1, entity2)

2. Watch the result in the Viewers sandbox.

15.4 Advanced Query language tutorial

1. For the sake of simplicity switch off the Query Explorer for the previous patterns with the following annota- tion:

@QueryExplorer(display = false)

2. Create Support patterns for the inheritance:

//@QueryExplorer(display = false) pattern superEnitities(entity, superEntity) { Entity.isA(entity, superEntity); }

//@QueryExplorer(display = false) pattern allSuperEntities(entity, superEntity) { find superEnitities+(entity, superEntity); }

3. Create a pattern that detects a circle in the type hierarchy:

pattern circleInTypeHierarchy(entity) { find allSuperEntities(entity, entity); }

109 4. Create a pattern that detects a (transitive) diamond in the type type hierarchy:

pattern diamondInTypeHierarchy(entity1, entity2, entity3, entity4) { find allSuperEntities(entity1,entity2); find allSuperEntities(entity1,entity3); entity2 != entity3; find allSuperEntities(entity2,entity4); find allSuperEntities(entity3,entity4); }

5. Every diamond has matched at least two times. This should be prevented if we make the pattern assimetric by defining somehow that entity2 < entity3. Let us define an ordering relation between the entities:

pattern order(a, b) { Entity.Name(a, name1); Entity.Name(b, name2); check( name1.compareTo(name2) <0 ); }

And change the diamond code:

pattern diamondInTypeHierarchy(entity1, entity2, entity3, entity4) { find allSuperEntities(entity1,entity2); find allSuperEntities(entity1,entity3); //entity2 != entity3; find order(entity2, entity3); find allSuperEntities(entity2,entity4); find allSuperEntities(entity3,entity4); }

6. By the way, calculate the infimum of the order:

pattern FirstInOrder(first: Entity) { neg find order(_, first); }

7. Extend the patterns to get the inherited relations and attributes too:

pattern attribute(entity, attribute) { Entity.attributes(entity,attribute); } or { find allSuperEntities(entity, superEntity); find attribute(superEntity, attribute); }

and

pattern relation(entity1, entity2) { Relation.leftEnding.target(relation, entity1); Relation.rightEnding.target(relation, entity2); } or { find allSuperEntities(entity1, superEntity); find relation(superEntity, entity2); }

110 8. Print out how many attributes a well-formed entity has:

@Item(item = entity, label = "$name$ ($attributes$)") pattern goodEntity(entity, name, attributes) { Entity.Name(entity, name); neg find badEntity(entity,_); attributes == count find attribute(entity,_); }

15.5 Validation

1. At first we need to import the query project to the host Eclipse. To do this copy the path of the project from the properties menu.

2. Close the project in the runtime Eclipse to avoid conflicts.

3. Go to the host Eclipse and import the query project.

4. Annote some pattern with @Constraint, like:

@Constraint(message = "The name is not unique!", location=entity1, severity = "error") pattern sameNamedEntities(entity1, entity2, commonName)

@Constraint(message = "The name is empty!", location=element, severity = "error") pattern emptyNamedElement(element: NamedElement)

5. Start the runtime Eclipse, open the instance model and right click on the resource and choose EMF-IncQuery validation | Initialize EMF-IncQuery validators on Editor.

6. If you make a mistake an error will rise.

15.6 Derived feature

1. Create a new EReference named otherEnding in the RelationEnding to itself. Set the following properties:

• Changeable = false • Derived = true • Transient = true • Volatile = false

2. Annote the pattern pattern other:

@QueryBasedFeature pattern other(ending:RelationEnding, other)

3. Start the runtime Eclipse and try the feature in the instance model.

111