Bump versions to 12.0.5-SNAPSHOT
[odlparent.git] / docs / developer-guide.rst
1 .. _odl-parent-developer-guide:
2
3 Developing with ODL Parent
4 ==========================
5
6 Parent POMs
7 -----------
8
9 Overview
10 ~~~~~~~~
11
12 The ODL Parent component for OpenDaylight provides a number of Maven
13 parent POMs which allow Maven projects to be easily integrated in the
14 OpenDaylight ecosystem. Technically, the aim of projects in OpenDaylight
15 is to produce Karaf features, and these parent projects provide common
16 support for the different types of projects involved.
17
18 These parent projects are:
19
20 -  ``odlparent-lite`` — the basic parent POM for Maven modules which
21    don’t produce artifacts (*e.g.* aggregator POMs)
22
23 -  ``odlparent`` — the common parent POM for Maven modules containing
24    Java code
25
26 -  ``bundle-parent`` — the parent POM for Maven modules producing OSGi
27    bundles
28
29 -  ``single-feature-parent`` — the parent POM for Maven modules producing
30    a single Karaf 4 feature
31
32 -  ``feature-repo-parent`` — the parent POM for Maven modules producing
33    Karaf 4 feature repositories
34
35 -  ``karaf4-parent`` — the parent POM for Maven modules producing Karaf 4
36    distributions
37
38 -  ``karaf-dist-static`` - the parent POM for Maven modules producing Karaf 4
39    static distributions
40
41 odlparent-lite
42 ~~~~~~~~~~~~~~
43
44 This is the base parent for all OpenDaylight Maven projects and
45 modules. It provides the following, notably to allow publishing
46 artifacts to Maven Central:
47
48 -  license information;
49
50 -  organization information;
51
52 -  issue management information (a link to our Bugzilla);
53
54 -  continuous integration information (a link to our Jenkins setup);
55
56 -  default Maven plugins (``maven-clean-plugin``,
57    ``maven-deploy-plugin``, ``maven-install-plugin``,
58    ``maven-javadoc-plugin`` with HelpMojo support,
59    ``maven-project-info-reports-plugin``, ``maven-site-plugin`` with
60    Asciidoc support, ``jdepend-maven-plugin``);
61
62 -  distribution management information.
63
64 It also defines two profiles which help during development:
65
66 -  ``q`` (``-Pq``), the quick profile, which disables tests, code
67    coverage, Javadoc generation, code analysis, etc. — anything which
68    isn’t necessary to build the bundles and features (see `this blog
69    post <http://blog2.vorburger.ch/2016/06/improve-maven-build-speed-with-q.html>`__
70    for details);
71
72 -  ``addInstallRepositoryPath``
73    (``-DaddInstallRepositoryPath=…/karaf/system``) which can be used to
74    drop a bundle in the appropriate Karaf location, to enable
75    hot-reloading of bundles during development (see `this blog
76    post <http://blog2.vorburger.ch/2016/06/maven-install-into-additional.html>`__
77    for details).
78
79 For modules which don’t produce any useful artifacts (*e.g.* aggregator
80 POMs), you should add the following to avoid processing artifacts:
81
82 ::
83
84     <build>
85         <plugins>
86             <plugin>
87                 <groupId>org.apache.maven.plugins</groupId>
88                 <artifactId>maven-deploy-plugin</artifactId>
89                 <configuration>
90                     <skip>true</skip>
91                 </configuration>
92             </plugin>
93             <plugin>
94                 <groupId>org.apache.maven.plugins</groupId>
95                 <artifactId>maven-install-plugin</artifactId>
96                 <configuration>
97                     <skip>true</skip>
98                 </configuration>
99             </plugin>
100         </plugins>
101     </build>
102
103 odlparent
104 ~~~~~~~~~
105
106 This inherits from ``odlparent-lite`` and mainly provides dependency and
107 plugin management for OpenDaylight projects.
108
109 If you use any of the following libraries, you should rely on
110 ``odlparent`` to provide the appropriate versions:
111
112 -  Akka (and Scala)
113
114 -  Apache Commons:
115
116    -  ``commons-codec``
117
118    -  ``commons-fileupload``
119
120    -  ``commons-io``
121
122    -  ``commons-lang``
123
124    -  ``commons-lang3``
125
126    -  ``commons-net``
127
128 -  Apache Shiro
129
130 -  Guava
131
132 -  JAX-RS with Jersey
133
134 -  JSON processing:
135
136    -  GSON
137
138    -  Jackson
139
140 -  Logging:
141
142    -  Logback
143
144    -  SLF4J
145
146 -  Netty
147
148 -  OSGi:
149
150    -  Apache Felix
151
152    -  core OSGi dependencies (``core``, ``compendium``\ …)
153
154 -  Testing:
155
156    -  Hamcrest
157
158    -  JSON assert
159
160    -  JUnit
161
162    -  Mockito
163
164    -  Pax Exam
165
166    -  PowerMock
167
168 -  XML/XSL:
169
170    -  Xerces
171
172    -  XML APIs
173
174 .. note::
175
176     This list isn’t exhaustive. It’s also not cast in stone; if you’d
177     like to add a new dependency (or migrate a dependency), please
178     contact `the mailing
179     list <https://lists.opendaylight.org/mailman/listinfo/odlparent-dev>`__.
180
181 ``odlparent`` also enforces some Checkstyle verification rules. In
182 particular, it enforces the common license header used in all
183 OpenDaylight code:
184
185 ::
186
187     /*
188      * Copyright © ${year} ${holder} and others.  All rights reserved.
189      *
190      * This program and the accompanying materials are made available under the
191      * terms of the Eclipse Public License v1.0 which accompanies this distribution,
192      * and is available at http://www.eclipse.org/legal/epl-v10.html
193      */
194
195 where “\ ``${year}``\ ” is initially the first year of publication, then
196 (after a year has passed) the first and latest years of publication,
197 separated by commas (*e.g.* “2014, 2016”), and “\ ``${holder}``\ ” is
198 the initial copyright holder (typically, the first author’s employer).
199 “All rights reserved” is optional.
200
201 If you need to disable this license check, *e.g.* for files imported
202 under another license (EPL-compatible of course), you can override the
203 ``maven-checkstyle-plugin`` configuration. ``features-test`` does this
204 for its ``CustomBundleUrlStreamHandlerFactory`` class, which is
205 ASL-licensed:
206
207 ::
208
209     <plugin>
210         <artifactId>maven-checkstyle-plugin</artifactId>
211         <executions>
212             <execution>
213                 <id>check-license</id>
214                 <goals>
215                     <goal>check</goal>
216                 </goals>
217                 <phase>process-sources</phase>
218                 <configuration>
219                     <configLocation>check-license.xml</configLocation>
220                     <headerLocation>EPL-LICENSE.regexp.txt</headerLocation>
221                     <includeResources>false</includeResources>
222                     <includeTestResources>false</includeTestResources>
223                     <sourceDirectory>${project.build.sourceDirectory}</sourceDirectory>
224                     <excludes>
225                         <!-- Skip Apache Licensed files -->
226                         org/opendaylight/odlparent/featuretest/CustomBundleUrlStreamHandlerFactory.java
227                     </excludes>
228                     <failsOnError>false</failsOnError>
229                     <consoleOutput>true</consoleOutput>
230                 </configuration>
231             </execution>
232         </executions>
233     </plugin>
234
235 bundle-parent
236 ~~~~~~~~~~~~~
237
238 This inherits from ``odlparent`` and enables functionality useful for
239 OSGi bundles:
240
241 -  ``maven-javadoc-plugin`` is activated, to build the Javadoc JAR;
242
243 -  ``maven-source-plugin`` is activated, to build the source JAR;
244
245 -  ``maven-bundle-plugin`` is activated (including extensions), to build
246    OSGi bundles (using the “bundle” packaging).
247
248 In addition to this, JUnit is included as a default dependency in “test”
249 scope.
250
251 features-parent
252 ~~~~~~~~~~~~~~~
253
254 This inherits from ``odlparent`` and enables functionality useful for
255 Karaf features:
256
257 -  ``karaf-maven-plugin`` is activated, to build Karaf features — but
258    for OpenDaylight, projects need to use “jar” packaging (**not**
259    “feature” or “kar”);
260
261 -  ``features.xml`` files are processed from templates stored in
262    ``src/main/features/features.xml``;
263
264 -  Karaf features are tested after build to ensure they can be activated
265    in a Karaf container.
266
267 The ``features.xml`` processing allows versions to be ommitted from
268 certain feature dependencies, and replaced with “\ ``{{version}}``\ ”.
269 For example:
270
271 ::
272
273     <features name="odl-mdsal-${project.version}" xmlns="http://karaf.apache.org/xmlns/features/v1.2.0"
274        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
275        xsi:schemaLocation="http://karaf.apache.org/xmlns/features/v1.2.0 http://karaf.apache.org/xmlns/features/v1.2.0">
276
277         <repository>mvn:org.opendaylight.odlparent/features-odlparent/{{VERSION}}/xml/features</repository>
278
279         [...]
280         <feature name='odl-mdsal-broker-local' version='${project.version}' description="OpenDaylight :: MDSAL :: Broker">
281             <feature version='${yangtools.version}'>odl-yangtools-common</feature>
282             <feature version='${mdsal.version}'>odl-mdsal-binding-dom-adapter</feature>
283             <feature version='${mdsal.model.version}'>odl-mdsal-models</feature>
284             <feature version='${project.version}'>odl-mdsal-common</feature>
285             <feature version='${config.version}'>odl-config-startup</feature>
286             <feature version='${config.version}'>odl-config-netty</feature>
287             <feature version='[3.3.0,4.0.0)'>odl-lmax</feature>
288             [...]
289             <bundle>mvn:org.opendaylight.controller/sal-dom-broker-config/{{VERSION}}</bundle>
290             <bundle start-level="40">mvn:org.opendaylight.controller/blueprint/{{VERSION}}</bundle>
291             <configfile finalname="${config.configfile.directory}/${config.mdsal.configfile}">mvn:org.opendaylight.controller/md-sal-config/{{VERSION}}/xml/config</configfile>
292         </feature>
293
294 As illustrated, versions can be ommitted in this way for repository
295 dependencies, bundle dependencies and configuration files. They must be
296 specified traditionally (either hard-coded, or using Maven properties)
297 for feature dependencies.
298
299 karaf-parent
300 ~~~~~~~~~~~~
301
302 This allows building a Karaf 3 distribution, typically for local testing
303 purposes. Any runtime-scoped feature dependencies will be included in the
304 distribution, and the ``karaf.localFeature`` property can be used to
305 specify the boot feature (in addition to ``standard``).
306
307 single-feature-parent
308 ~~~~~~~~~~~~~~~~~~~~~
309
310 This inherits from ``odlparent`` and enables functionality useful for
311 Karaf 4 features:
312
313 -  ``karaf-maven-plugin`` is activated, to build Karaf features, typically
314    with “feature” packaging (“kar” is also supported);
315
316 -  ``feature.xml`` files are generated based on the compile-scope dependencies
317    defined in the POM, optionally initialised from a stub in
318    ``src/main/feature/feature.xml``.
319
320 -  Karaf features are tested after build to ensure they can be activated
321    in a Karaf container.
322
323 The ``feature.xml`` processing adds transitive dependencies by default, which
324 allows features to be defined using only the most significant dependencies
325 (those that define the feature); other requirements are determined
326 automatically as long as they exist as Maven dependencies.
327
328 “configfiles” need to be defined both as Maven dependencies (with the
329 appropriate type and classifier) and as ``<configfile>`` elements in the
330 ``feature.xml`` stub.
331
332 Other features which a feature depends on need to be defined as Maven
333 dependencies with type “xml” and classifier “features” (note the plural here).
334
335 feature-repo-parent
336 ~~~~~~~~~~~~~~~~~~~
337
338 This inherits from ``odlparent`` and enables functionality useful for
339 Karaf 4 feature repositories. It follows the same principles as
340 ``single-feature-parent``, but is designed specifically for repositories
341 and should be used only for this type of artifacts.
342
343 It builds a feature repository referencing all the (feature) dependencies
344 listed in the POM.
345
346 karaf4-parent
347 ~~~~~~~~~~~~~
348
349 This allows building a Karaf 4 distribution, typically for local testing
350 purposes. Any runtime-scoped feature dependencies will be included in the
351 distribution, and the ``karaf.localFeature`` property can be used to
352 specify the boot feature (in addition to ``standard``).
353
354 karaf-dist-static
355 ~~~~~~~~~~~~~~~~~
356
357 This allows building a kind of immutable static distribution by adding
358 this as a parent to your project's pom.xml. This pom file defines the static
359 karaf framework alongside common OpenDaylight's components(branding,
360 bouncycastle items, etc). The major difference to the dynamic distribution is
361 that validation of features dependencies happens during the build phase and
362 all of the dependencies are installed as *"reference:file:url"* into the
363 *"etc/startup.properties"*. Static distribution might be the right choice when
364 you need to to produce a lightweight and immutable package for your deployment.
365 You can find a ``test-static`` project that inherits from ``karaf-dist-static``
366 and demonstrates how this parent can be used.
367
368 Generally speaking, to build a static distribution with selected for your
369 purposes features, you have to follow the next two steps:
370
371 1. Add features you want to be included in distribution under the
372    dependencies block.
373
374 .. code:: xml
375
376     <dependencies>
377         <dependency>
378             <groupId>org.opendaylight.odlparent</groupId>
379             <artifactId>odl-dropwizard-metrics</artifactId>
380             <version>${project.version}</version>
381             <type>xml</type>
382             <classifier>features</classifier>
383         </dependency>
384         <dependency>
385             <groupId>org.opendaylight.odlparent</groupId>
386             <artifactId>odl-gson</artifactId>
387             <version>${project.version}</version>
388             <type>xml</type>
389             <classifier>features</classifier>
390         </dependency>
391     </dependencies>
392
393 2. Put additional configuration for the karaf-maven-plugin about these features:
394
395 .. code:: xml
396
397             <plugin>
398                 <groupId>org.apache.karaf.tooling</groupId>
399                 <artifactId>karaf-maven-plugin</artifactId>
400                 <extensions>true</extensions>
401                 <configuration>
402                     <startupFeatures combine.children="append">
403                         <feature>shell</feature>
404                     </startupFeatures>
405                     <bootFeatures combine.children="append">
406                         <feature>odl-dropwizard-metrics</feature>
407                         <feature>odl-gson</feature>
408                     </bootFeatures>
409                 </configuration>
410             </plugin>
411
412 .. note::  If you need to add something from the default karaf features
413            (like ``shell`` feature in our example), you should use
414            **<startupFeatures>** block, and not forget about
415            **combine.children="append"** attribute. Everything else can
416            be added to the bootFeatures block.
417
418
419 **Known issues**
420
421 * An issue with FeatureDeploymentListener.bundleChanged and NPE records in
422   log files. More details available here:
423   https://issues.apache.org/jira/browse/KARAF-6612
424
425 * Some of the features might try to update configuration files, but that's
426   not supported by static distribution, so StaticConfigurationImpl.update
427   will throw UnsupportedOperationException.
428
429 Features (for Karaf 3)
430 ----------------------
431
432 The ODL Parent component for OpenDaylight provides a number of Karaf 3
433 features which can be used by other Karaf 3 features to use certain
434 third-party upstream dependencies.
435
436 These features are:
437
438 -  Akka features (in the ``features-akka`` repository):
439
440    -  ``odl-akka-all`` — all Akka bundles;
441
442    -  ``odl-akka-scala-2.11`` — Scala runtime for OpenDaylight;
443
444    -  ``odl-akka-system-2.4`` — Akka actor framework bundles;
445
446    -  ``odl-akka-clustering-2.4`` — Akka clustering bundles and
447       dependencies;
448
449    -  ``odl-akka-leveldb-0.7`` — LevelDB;
450
451    -  ``odl-akka-persistence-2.4`` — Akka persistence;
452
453 -  general third-party features (in the ``features-odlparent``
454    repository):
455
456    -  ``odl-netty-4`` — all Netty bundles;
457
458    -  ``odl-guava-18`` — Guava 18;
459
460    -  ``odl-guava-21`` — Guava 21 (not indended for use in Carbon);
461
462    -  ``odl-lmax-3`` — LMAX Disruptor;
463
464    -  ``odl-triemap-0.2`` — Concurrent Trie HashMap.
465
466 To use these, you need to declare a dependency on the appropriate
467 repository in your ``features.xml`` file:
468
469 ::
470
471     <repository>mvn:org.opendaylight.odlparent/features-odlparent/{{VERSION}}/xml/features</repository>
472
473 and then include the feature, *e.g.*:
474
475 ::
476
477     <feature name='odl-mdsal-broker-local' version='${project.version}' description="OpenDaylight :: MDSAL :: Broker">
478         [...]
479         <feature version='[3.3.0,4.0.0)'>odl-lmax</feature>
480         [...]
481     </feature>
482
483 You also need to depend on the features repository in your POM:
484
485 ::
486
487     <dependency>
488         <groupId>org.opendaylight.odlparent</groupId>
489         <artifactId>features-odlparent</artifactId>
490         <classifier>features</classifier>
491         <type>xml</type>
492     </dependency>
493
494 assuming the appropriate dependency management:
495
496 ::
497
498     <dependencyManagement>
499         <dependencies>
500             <dependency>
501                 <groupId>org.opendaylight.odlparent</groupId>
502                 <artifactId>odlparent-artifacts</artifactId>
503                 <version>1.8.0-SNAPSHOT</version>
504                 <scope>import</scope>
505                 <type>pom</type>
506             </dependency>
507         </dependencies>
508     </dependencyManagement>
509
510 (the version number there is appropriate for Carbon). For the time being
511 you also need to depend separately on the individual JARs as
512 compile-time dependencies to build your dependent code; the relevant
513 dependencies are managed in ``odlparent``'s dependency management.
514
515 | The suggested version ranges are as follows:
516
517 -  ``odl-netty``: ``[4.0.37,4.1.0)`` or ``[4.0.37,5.0.0)``;
518
519 -  ``odl-guava``: ``[18,19)`` (if your code is ready for it, ``[19,20)``
520    is also available, but the current default version of Guava in
521    OpenDaylight is 18);
522
523 -  ``odl-lmax``: ``[3.3.4,4.0.0)``
524
525 Features (for Karaf 4)
526 ----------------------
527
528 There are equivalent features to all the Karaf 3 features, for Karaf 4.
529 The repositories use “features4” instead of “features”, and the features
530 use “odl4” instead of “odl”.
531
532 The following new features are specific to Karaf 4:
533
534 -  Karaf wrapper features (also in the ``features4-odlparent``
535    repository) — these can be used to pull in a Karaf feature
536    using a Maven dependency in a POM:
537
538    -  ``odl-karaf-feat-feature`` — the Karaf ``feature`` feature;
539
540    -  ``odl-karaf-feat-jdbc`` — the Karaf ``jdbc`` feature;
541
542    -  ``odl-karaf-feat-jetty`` — the Karaf ``jetty`` feature;
543
544    -  ``odl-karaf-feat-war`` — the Karaf ``war`` feature.
545
546 To use these, all you need to do now is add the appropriate dependency
547 in your feature POM; for example:
548
549 ::
550
551     <dependency>
552         <groupId>org.opendaylight.odlparent</groupId>
553         <artifactId>odl4-guava-18</artifactId>
554         <classifier>features</classifier>
555         <type>xml</type>
556     </dependency>
557
558 assuming the appropriate dependency management:
559
560 ::
561
562     <dependencyManagement>
563         <dependencies>
564             <dependency>
565                 <groupId>org.opendaylight.odlparent</groupId>
566                 <artifactId>odlparent-artifacts</artifactId>
567                 <version>1.8.0-SNAPSHOT</version>
568                 <scope>import</scope>
569                 <type>pom</type>
570             </dependency>
571         </dependencies>
572     </dependencyManagement>
573
574 (the version number there is appropriate for Carbon). We no longer use version
575 ranges, the feature dependencies all use the ``odlparent`` version (but you
576 should rely on the artifacts POM).