Model Driven Software Development and Service Integration

Model Driven Software Development and Service Integration
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
May 10, 2013
Gábor Szárnyas
Contents
1 Introduction
6
2 An overview of the Eclipse development environment
7
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/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 distribution’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:
<natures>
<nature>org.eclipse.jdt.core.javanature</nature>
<nature>org.eclipse.pde.PluginNature</nature>
</natures>
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:
<buildSpec>
<buildCommand>
<name>org.eclipse.jdt.core.javabuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.pde.ManifestBuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.pde.SchemaBuilder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
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, Linux 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:
<!-- This is an extension of "org.eclipse.ui.handlers". -->
<extension
point="org.eclipse.ui.handlers">
<!-- If a command named "hu.bme.mit.JPADataCompileButton.GenerateCommand"
fires then call the execute method of the class named
"hu.bme.mit.JPADataCompileButton.GenerateCommand".-->
<handler
class="hu.bme.mit.compilecommandhandler.JPADataGenerateCommandHandler"
commandId="hu.bme.mit.JPADataCompileButton.GenerateCommand">
</handler>
</extension>
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 Development and Integration (http://www.inf.mit.bme.hu/edu/courses/eafi), Model Driven Software Development (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
private
private
private
}
Car {
String numberplate;
int yearOfManufacture;
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<Car> cars = new LinkedList<Car>();
Random random = new Random();
for (int i = 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<Car> cars = new LinkedList<Car>();
Random random = new Random();
for (int i = 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 executionspecific 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<String> applicationNames = new LinkedList<String>()
for (int i = 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 basically 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.
${username}.
Add a message saying The following user has logged out:
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 implementation 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 external 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
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
import
import
import
java.util.ArrayList;
java.util.HashMap;
java.util.List;
java.util.Map;
public enum ApplicationProvider {
instance;
private Map<Integer, Application> map = new HashMap<>();
private int lastId = 0;
public Application getApplication(int id) {
return map.get(id);
}
public List<Application> 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
named
}
}
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<Application> 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:
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<soapenv:Envelope
xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<soapenv:Body>
<insertApplication xmlns="http://ws.server.appstore.inf.mit.bme.hu">
<application>
<ns1:id xmlns:ns1="http://model.data.appstore.inf.mit.bme.hu">3</ns1:id>
<ns2:name xmlns:ns2="http://model.data.appstore.inf.mit.bme.hu">News</ns2:name>
</application>
</insertApplication>
</soapenv:Body>
</soapenv:Envelope>
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 <project> element:
<dependencies>
<dependency>
<groupId>com.sun.jersey</groupId>
<artifactId>jersey-server</artifactId>
<version>1.17</version>
</dependency>
<dependency>
<groupId>com.sun.jersey</groupId>
<artifactId>jersey-bundle</artifactId>
<version>1.17</version>
</dependency>
</dependencies>
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 <web-app> element
and paste the following:
<display-name></display-name>
<servlet>
<servlet-name></servlet-name>
<servlet-class>com.sun.jersey.spi.container.servlet.ServletContainer</servlet-class>
<init-param>
<param-name>com.sun.jersey.config.property.packages</param-name>
<param-value></param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name></servlet-name>
<url-pattern></url-pattern>
</servlet-mapping>
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 defined 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
<?xml version="1.0" encoding="UTF-8"?>
<project-modules id="moduleCoreId" project-version="1.5.0">
<wb-module deploy-name="[deployment-name]">
<wb-resource deploy-path="/" source-path="/WebContent" tag="defaultRootSource" />
<wb-resource deploy-path="/WEB-INF/classes" source-path="/src" />
<property name="context-root" value="[context-root]" />
<property name="java-output-path" value="/[java-output-path]/build/classes" />
</wb-module>
</project-modules>
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
import
import
import
import
import
import
import
import
import
javax.ws.rs.Consumes;
javax.ws.rs.GET;
javax.ws.rs.POST;
javax.ws.rs.Path;
javax.ws.rs.PathParam;
javax.ws.rs.Produces;
javax.ws.rs.core.Context;
javax.ws.rs.core.MediaType;
javax.ws.rs.core.Response;
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<Application> 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 <tomcat-users> element:
<role rolename="manager-gui"/>
<user name="admin" password="admin" roles="admin-gui,manager-gui"/>
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
<application>
<name>News</name>
</application>
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 computing platform for developing and hosting web applications in Google-managed data centers. 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 (int i = 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 Statechart 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.
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<soapenv:Body>
<generateApplications xmlns="http://ws.server.appstore.inf.mit.bme.hu">
67
<count>20</count>
</generateApplications>
</soapenv:Body>
</soapenv:Envelope>
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<apps.length; i++){
ret.add(apps.item(i).textContent)
}
return ret
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<String> results;
@Override
protected void executeConnector() throws Exception {
results = new ArrayList<String>();
results.add("A");
results.add("B");
}
@Override
protected List<ConnectorError> 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
import
import
import
import
java.io.InputStream;
java.net.URL;
java.net.URLConnection;
java.util.ArrayList;
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<String> 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<String>();
NodeList apps = document.getElementsByTagName("applications").item(0).getChildNodes();
for(int i = 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<ConnectorError> 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 ERDiagram.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 composition 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 command.
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
hu.bme.mit.mdsd.erdiagrammanipulator.
2. Add the following dependencies:
80
|
New
|
Plug-in
Project.
Name
it
to
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 expressions 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<Producer> productRange = new ArrayList<Producer>();
}
4. And a one named Producer:
public class Producer {
private String name;
private List<Dealer> worksWith = new ArrayList<Dealer>();
}
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:
<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.0"
xmlns="http://java.sun.com/xml/ns/persistence"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence
<persistence-unit name="cars">
<exclude-unlisted-classes>false</exclude-unlisted-classes>
<properties>
<property name="javax.persistence.jdbc.password" value="root"/>
<property name="javax.persistence.jdbc.user" value="root"/>
<property name="javax.persistence.jdbc.driver" value="com.mysql.jdbc.Driver"/>
<property name="javax.persistence.jdbc.url" value="jdbc:mysql://localhost:3306/test"/>
<property name="eclipselink.ddl-generation" value="create-tables"/>
<property name="eclipselink.logging.level" value="INFO"/>
</properties>
</persistence-unit>
</persistence>
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?
Add @Entity, the @Table(name="Producer_Table") and the
@Table(name="Dealer_Table") annotation to the respective persistent classes.
10. Annote the 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<Dealer> worksWith = new ArrayList<Dealer>();
And in Dealer:
@ManyToMany(mappedBy="worksWith")
private List<Producer> productRange = new ArrayList<Producer>();
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,
manager.linkDealerToProducer(dealer2,
manager.linkDealerToProducer(dealer2,
manager.linkDealerToProducer(dealer3,
manager.linkDealerToProducer(dealer3,
producer2);
producer1);
producer3);
producer2);
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<Producer> 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 createtables
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.
the
handed
out
code:
the
hu.bme.mit.mdsd.generatebutton
and
the
2. Check
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
JPADataGenerateCommandHandler class. The method structured like this:
•
•
•
•
•
execute
method
of
the
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 <name>.java will be placed into this folder with the content defined by the content parameter,
where <name> 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.
<dependency>
<groupId>org.neo4j</groupId>
<artifactId>neo4j</artifactId>
<version>1.8.2</version>
</dependency>
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
import
import
import
import
import
import
import
import
import
org.neo4j.cypher.javacompat.ExecutionEngine;
org.neo4j.cypher.javacompat.ExecutionResult;
org.neo4j.graphdb.GraphDatabaseService;
org.neo4j.graphdb.Node;
org.neo4j.graphdb.RelationshipType;
org.neo4j.graphdb.Transaction;
org.neo4j.graphdb.factory.GraphDatabaseFactory;
org.neo4j.graphdb.index.Index;
org.neo4j.graphdb.index.IndexManager;
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<Node> 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<String, Object> 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 variables. . . | System variables. Set the following variables:
• M2_HOME = c:\apache-maven-3.0.5
• M2 = %M2_HOME%\bin
• Path = <previous value of 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:
<dependency>
<groupId>org.neo4j</groupId>
<artifactId>neo4j-rest-graphdb</artifactId>
<version>1.8.2</version>
</dependency>
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
import
import
import
import
import
org.neo4j.helpers.collection.IteratorUtil;
org.neo4j.helpers.collection.MapUtil;
org.neo4j.rest.graphdb.RestAPI;
org.neo4j.rest.graphdb.RestAPIFacade;
org.neo4j.rest.graphdb.query.RestCypherQueryEngine;
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<Map<String, Object>> queryResult = queryEngine.query(query, MapUtil.map());
Collection<Map<String, Object>> result = IteratorUtil.asCollection(queryResult);
104
for (Map<String, Object> 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 annotation:
@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
Was this manual useful for you? yes no
Thank you for your participation!

* Your assessment is very important for improving the work of artificial intelligence, which forms the content of this project

Download PDF

advertisement