Sophie

Sophie

distrib > Mageia > 5 > i586 > media > core-release > by-pkgid > ad683afb20fdfb611550541dc1982531 > files > 38

javapackages-tools-doc-4.1.0-15.mga5.noarch.rpm

<!DOCTYPE html>
<html lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<meta name="generator" content="AsciiDoc 8.6.9">
<title>Java Packaging HOWTO</title>
<style type="text/css">
/* Shared CSS for AsciiDoc xhtml11 and html5 backends */

/* Default font. */
body {
  font-family: Georgia,serif;
}

/* Title font. */
h1, h2, h3, h4, h5, h6,
div.title, caption.title,
thead, p.table.header,
#toctitle,
#author, #revnumber, #revdate, #revremark,
#footer {
  font-family: Arial,Helvetica,sans-serif;
}

body {
  margin: 1em 5% 1em 5%;
}

a {
  color: blue;
  text-decoration: underline;
}
a:visited {
  color: fuchsia;
}

em {
  font-style: italic;
  color: navy;
}

strong {
  font-weight: bold;
  color: #083194;
}

h1, h2, h3, h4, h5, h6 {
  color: #527bbd;
  margin-top: 1.2em;
  margin-bottom: 0.5em;
  line-height: 1.3;
}

h1, h2, h3 {
  border-bottom: 2px solid silver;
}
h2 {
  padding-top: 0.5em;
}
h3 {
  float: left;
}
h3 + * {
  clear: left;
}
h5 {
  font-size: 1.0em;
}

div.sectionbody {
  margin-left: 0;
}

hr {
  border: 1px solid silver;
}

p {
  margin-top: 0.5em;
  margin-bottom: 0.5em;
}

ul, ol, li > p {
  margin-top: 0;
}
ul > li     { color: #aaa; }
ul > li > * { color: black; }

pre {
  padding: 0;
  margin: 0;
}

#author {
  color: #527bbd;
  font-weight: bold;
  font-size: 1.1em;
}
#email {
}
#revnumber, #revdate, #revremark {
}

#footer {
  font-size: small;
  border-top: 2px solid silver;
  padding-top: 0.5em;
  margin-top: 4.0em;
}
#footer-text {
  float: left;
  padding-bottom: 0.5em;
}
#footer-badges {
  float: right;
  padding-bottom: 0.5em;
}

#preamble {
  margin-top: 1.5em;
  margin-bottom: 1.5em;
}
div.imageblock, div.exampleblock, div.verseblock,
div.quoteblock, div.literalblock, div.listingblock, div.sidebarblock,
div.admonitionblock {
  margin-top: 1.0em;
  margin-bottom: 1.5em;
}
div.admonitionblock {
  margin-top: 2.0em;
  margin-bottom: 2.0em;
  margin-right: 10%;
  color: #606060;
}

div.content { /* Block element content. */
  padding: 0;
}

/* Block element titles. */
div.title, caption.title {
  color: #527bbd;
  font-weight: bold;
  text-align: left;
  margin-top: 1.0em;
  margin-bottom: 0.5em;
}
div.title + * {
  margin-top: 0;
}

td div.title:first-child {
  margin-top: 0.0em;
}
div.content div.title:first-child {
  margin-top: 0.0em;
}
div.content + div.title {
  margin-top: 0.0em;
}

div.sidebarblock > div.content {
  background: #ffffee;
  border: 1px solid #dddddd;
  border-left: 4px solid #f0f0f0;
  padding: 0.5em;
}

div.listingblock > div.content {
  border: 1px solid #dddddd;
  border-left: 5px solid #f0f0f0;
  background: #f8f8f8;
  padding: 0.5em;
}

div.quoteblock, div.verseblock {
  padding-left: 1.0em;
  margin-left: 1.0em;
  margin-right: 10%;
  border-left: 5px solid #f0f0f0;
  color: #777777;
}

div.quoteblock > div.attribution {
  padding-top: 0.5em;
  text-align: right;
}

div.verseblock > pre.content {
  font-family: inherit;
  font-size: inherit;
}
div.verseblock > div.attribution {
  padding-top: 0.75em;
  text-align: left;
}
/* DEPRECATED: Pre version 8.2.7 verse style literal block. */
div.verseblock + div.attribution {
  text-align: left;
}

div.admonitionblock .icon {
  vertical-align: top;
  font-size: 1.1em;
  font-weight: bold;
  text-decoration: underline;
  color: #527bbd;
  padding-right: 0.5em;
}
div.admonitionblock td.content {
  padding-left: 0.5em;
  border-left: 3px solid #dddddd;
}

div.exampleblock > div.content {
  border-left: 3px solid #dddddd;
  padding-left: 0.5em;
}

div.imageblock div.content { padding-left: 0; }
span.image img { border-style: none; }
a.image:visited { color: white; }

dl {
  margin-top: 0.8em;
  margin-bottom: 0.8em;
}
dt {
  margin-top: 0.5em;
  margin-bottom: 0;
  font-style: normal;
  color: navy;
}
dd > *:first-child {
  margin-top: 0.1em;
}

ul, ol {
    list-style-position: outside;
}
ol.arabic {
  list-style-type: decimal;
}
ol.loweralpha {
  list-style-type: lower-alpha;
}
ol.upperalpha {
  list-style-type: upper-alpha;
}
ol.lowerroman {
  list-style-type: lower-roman;
}
ol.upperroman {
  list-style-type: upper-roman;
}

div.compact ul, div.compact ol,
div.compact p, div.compact p,
div.compact div, div.compact div {
  margin-top: 0.1em;
  margin-bottom: 0.1em;
}

tfoot {
  font-weight: bold;
}
td > div.verse {
  white-space: pre;
}

div.hdlist {
  margin-top: 0.8em;
  margin-bottom: 0.8em;
}
div.hdlist tr {
  padding-bottom: 15px;
}
dt.hdlist1.strong, td.hdlist1.strong {
  font-weight: bold;
}
td.hdlist1 {
  vertical-align: top;
  font-style: normal;
  padding-right: 0.8em;
  color: navy;
}
td.hdlist2 {
  vertical-align: top;
}
div.hdlist.compact tr {
  margin: 0;
  padding-bottom: 0;
}

.comment {
  background: yellow;
}

.footnote, .footnoteref {
  font-size: 0.8em;
}

span.footnote, span.footnoteref {
  vertical-align: super;
}

#footnotes {
  margin: 20px 0 20px 0;
  padding: 7px 0 0 0;
}

#footnotes div.footnote {
  margin: 0 0 5px 0;
}

#footnotes hr {
  border: none;
  border-top: 1px solid silver;
  height: 1px;
  text-align: left;
  margin-left: 0;
  width: 20%;
  min-width: 100px;
}

div.colist td {
  padding-right: 0.5em;
  padding-bottom: 0.3em;
  vertical-align: top;
}
div.colist td img {
  margin-top: 0.3em;
}

@media print {
  #footer-badges { display: none; }
}

#toc {
  margin-bottom: 2.5em;
}

#toctitle {
  color: #527bbd;
  font-size: 1.1em;
  font-weight: bold;
  margin-top: 1.0em;
  margin-bottom: 0.1em;
}

div.toclevel1, div.toclevel2, div.toclevel3, div.toclevel4 {
  margin-top: 0;
  margin-bottom: 0;
}
div.toclevel2 {
  margin-left: 2em;
  font-size: 0.9em;
}
div.toclevel3 {
  margin-left: 4em;
  font-size: 0.9em;
}
div.toclevel4 {
  margin-left: 6em;
  font-size: 0.9em;
}

span.aqua { color: aqua; }
span.black { color: black; }
span.blue { color: blue; }
span.fuchsia { color: fuchsia; }
span.gray { color: gray; }
span.green { color: green; }
span.lime { color: lime; }
span.maroon { color: maroon; }
span.navy { color: navy; }
span.olive { color: olive; }
span.purple { color: purple; }
span.red { color: red; }
span.silver { color: silver; }
span.teal { color: teal; }
span.white { color: white; }
span.yellow { color: yellow; }

span.aqua-background { background: aqua; }
span.black-background { background: black; }
span.blue-background { background: blue; }
span.fuchsia-background { background: fuchsia; }
span.gray-background { background: gray; }
span.green-background { background: green; }
span.lime-background { background: lime; }
span.maroon-background { background: maroon; }
span.navy-background { background: navy; }
span.olive-background { background: olive; }
span.purple-background { background: purple; }
span.red-background { background: red; }
span.silver-background { background: silver; }
span.teal-background { background: teal; }
span.white-background { background: white; }
span.yellow-background { background: yellow; }

span.big { font-size: 2em; }
span.small { font-size: 0.6em; }

span.underline { text-decoration: underline; }
span.overline { text-decoration: overline; }
span.line-through { text-decoration: line-through; }


/*
 * xhtml11 specific
 *
 * */

tt {
  font-family: monospace;
  font-size: inherit;
  color: navy;
}

div.tableblock {
  margin-top: 1.0em;
  margin-bottom: 1.5em;
}
div.tableblock > table {
  border: 3px solid #527bbd;
}
thead, p.table.header {
  font-weight: bold;
  color: #527bbd;
}
p.table {
  margin-top: 0;
}
/* Because the table frame attribute is overriden by CSS in most browsers. */
div.tableblock > table[frame="void"] {
  border-style: none;
}
div.tableblock > table[frame="hsides"] {
  border-left-style: none;
  border-right-style: none;
}
div.tableblock > table[frame="vsides"] {
  border-top-style: none;
  border-bottom-style: none;
}


/*
 * html5 specific
 *
 * */

.monospaced {
  font-family: monospace;
  font-size: inherit;
  color: navy;
}

table.tableblock {
  margin-top: 1.0em;
  margin-bottom: 1.5em;
}
thead, p.tableblock.header {
  font-weight: bold;
  color: #527bbd;
}
p.tableblock {
  margin-top: 0;
}
table.tableblock {
  border-width: 3px;
  border-spacing: 0px;
  border-style: solid;
  border-color: #527bbd;
  border-collapse: collapse;
}
th.tableblock, td.tableblock {
  border-width: 1px;
  padding: 4px;
  border-style: solid;
  border-color: #527bbd;
}

table.tableblock.frame-topbot {
  border-left-style: hidden;
  border-right-style: hidden;
}
table.tableblock.frame-sides {
  border-top-style: hidden;
  border-bottom-style: hidden;
}
table.tableblock.frame-none {
  border-style: hidden;
}

th.tableblock.halign-left, td.tableblock.halign-left {
  text-align: left;
}
th.tableblock.halign-center, td.tableblock.halign-center {
  text-align: center;
}
th.tableblock.halign-right, td.tableblock.halign-right {
  text-align: right;
}

th.tableblock.valign-top, td.tableblock.valign-top {
  vertical-align: top;
}
th.tableblock.valign-middle, td.tableblock.valign-middle {
  vertical-align: middle;
}
th.tableblock.valign-bottom, td.tableblock.valign-bottom {
  vertical-align: bottom;
}


/*
 * manpage specific
 *
 * */

body.manpage h1 {
  padding-top: 0.5em;
  padding-bottom: 0.5em;
  border-top: 2px solid silver;
  border-bottom: 2px solid silver;
}
body.manpage h2 {
  border-style: none;
}
body.manpage div.sectionbody {
  margin-left: 3em;
}

@media print {
  body.manpage div#toc { display: none; }
}


/*
 * Theme specific overrides of the preceding (asciidoc.css) CSS.
 *
 */
body {
  font-family: Garamond, Georgia, serif;
  font-size: 17px;
  color: #3E4349;
  line-height: 1.3em;
}
h1, h2, h3, h4, h5, h6,
div.title, caption.title,
thead, p.table.header,
#toctitle,
#author, #revnumber, #revdate, #revremark,
#footer {
  font-family: Garmond, Georgia, serif;
  font-weight: normal;
  border-bottom-width: 0;
  color: #3E4349;
}
div.title, caption.title { color: #596673; font-weight: bold; }
h1 { font-size: 240%; }
h2 { font-size: 180%; }
h3 { font-size: 150%; }
h4 { font-size: 130%; }
h5 { font-size: 115%; }
h6 { font-size: 100%; }
#header h1 { margin-top: 0; }
#toc {
  color: #444444;
  line-height: 1.5;
  padding-top: 1.5em;
}
#toctitle {
  font-size: 20px;
}
#toc a {
    border-bottom: 1px dotted #999999;
    color: #444444 !important;
    text-decoration: none !important;
}
#toc a:hover {
    border-bottom: 1px solid #6D4100;
    color: #6D4100 !important;
    text-decoration: none !important;
}
div.toclevel1 { margin-top: 0.2em; font-size: 16px; }
div.toclevel2 { margin-top: 0.15em; font-size: 14px; }
em, dt, td.hdlist1 { color: black; }
strong { color: #3E4349; }
a { color: #004B6B; text-decoration: none; border-bottom: 1px dotted #004B6B; }
a:visited { color: #615FA0; border-bottom: 1px dotted #615FA0; }
a:hover { color: #6D4100; border-bottom: 1px solid #6D4100; }
div.tableblock > table, table.tableblock { border: 3px solid #E8E8E8; }
th.tableblock, td.tableblock { border: 1px solid #E8E8E8; }
ul > li > * { color: #3E4349; }
pre, tt, .monospaced { font-family: Consolas,Menlo,'Deja Vu Sans Mono','Bitstream Vera Sans Mono',monospace; }
tt, .monospaced { font-size: 0.9em; color: black;
}
div.exampleblock > div.content, div.sidebarblock > div.content, div.listingblock > div.content { border-width: 0 0 0 3px; border-color: #E8E8E8; }
div.verseblock { border-left-width: 0; margin-left: 3em; }
div.quoteblock { border-left-width: 3px; margin-left: 0; margin-right: 0;}
div.admonitionblock td.content { border-left: 3px solid #E8E8E8; }


@media screen {
  body {
    max-width: 50em; /* approximately 80 characters wide */
    margin-left: 16em;
  }

  #toc {
    position: fixed;
    top: 0;
    left: 0;
    bottom: 0;
    width: 13em;
    padding: 0.5em;
    padding-bottom: 1.5em;
    margin: 0;
    overflow: auto;
    border-right: 3px solid #f8f8f8;
    background-color: white;
  }

  #toc .toclevel1 {
    margin-top: 0.5em;
  }

  #toc .toclevel2 {
    margin-top: 0.25em;
    display: list-item;
    color: #aaaaaa;
  }

  #toctitle {
    margin-top: 0.5em;
  }
}
</style>
<script type="text/javascript">
/*<![CDATA[*/
var asciidoc = {  // Namespace.

/////////////////////////////////////////////////////////////////////
// Table Of Contents generator
/////////////////////////////////////////////////////////////////////

/* Author: Mihai Bazon, September 2002
 * http://students.infoiasi.ro/~mishoo
 *
 * Table Of Content generator
 * Version: 0.4
 *
 * Feel free to use this script under the terms of the GNU General Public
 * License, as long as you do not remove or alter this notice.
 */

 /* modified by Troy D. Hanson, September 2006. License: GPL */
 /* modified by Stuart Rackham, 2006, 2009. License: GPL */

// toclevels = 1..4.
toc: function (toclevels) {

  function getText(el) {
    var text = "";
    for (var i = el.firstChild; i != null; i = i.nextSibling) {
      if (i.nodeType == 3 /* Node.TEXT_NODE */) // IE doesn't speak constants.
        text += i.data;
      else if (i.firstChild != null)
        text += getText(i);
    }
    return text;
  }

  function TocEntry(el, text, toclevel) {
    this.element = el;
    this.text = text;
    this.toclevel = toclevel;
  }

  function tocEntries(el, toclevels) {
    var result = new Array;
    var re = new RegExp('[hH]([1-'+(toclevels+1)+'])');
    // Function that scans the DOM tree for header elements (the DOM2
    // nodeIterator API would be a better technique but not supported by all
    // browsers).
    var iterate = function (el) {
      for (var i = el.firstChild; i != null; i = i.nextSibling) {
        if (i.nodeType == 1 /* Node.ELEMENT_NODE */) {
          var mo = re.exec(i.tagName);
          if (mo && (i.getAttribute("class") || i.getAttribute("className")) != "float") {
            result[result.length] = new TocEntry(i, getText(i), mo[1]-1);
          }
          iterate(i);
        }
      }
    }
    iterate(el);
    return result;
  }

  var toc = document.getElementById("toc");
  if (!toc) {
    return;
  }

  // Delete existing TOC entries in case we're reloading the TOC.
  var tocEntriesToRemove = [];
  var i;
  for (i = 0; i < toc.childNodes.length; i++) {
    var entry = toc.childNodes[i];
    if (entry.nodeName.toLowerCase() == 'div'
     && entry.getAttribute("class")
     && entry.getAttribute("class").match(/^toclevel/))
      tocEntriesToRemove.push(entry);
  }
  for (i = 0; i < tocEntriesToRemove.length; i++) {
    toc.removeChild(tocEntriesToRemove[i]);
  }

  // Rebuild TOC entries.
  var entries = tocEntries(document.getElementById("content"), toclevels);
  for (var i = 0; i < entries.length; ++i) {
    var entry = entries[i];
    if (entry.element.id == "")
      entry.element.id = "_toc_" + i;
    var a = document.createElement("a");
    a.href = "#" + entry.element.id;
    a.appendChild(document.createTextNode(entry.text));
    var div = document.createElement("div");
    div.appendChild(a);
    div.className = "toclevel" + entry.toclevel;
    toc.appendChild(div);
  }
  if (entries.length == 0)
    toc.parentNode.removeChild(toc);
},


/////////////////////////////////////////////////////////////////////
// Footnotes generator
/////////////////////////////////////////////////////////////////////

/* Based on footnote generation code from:
 * http://www.brandspankingnew.net/archive/2005/07/format_footnote.html
 */

footnotes: function () {
  // Delete existing footnote entries in case we're reloading the footnodes.
  var i;
  var noteholder = document.getElementById("footnotes");
  if (!noteholder) {
    return;
  }
  var entriesToRemove = [];
  for (i = 0; i < noteholder.childNodes.length; i++) {
    var entry = noteholder.childNodes[i];
    if (entry.nodeName.toLowerCase() == 'div' && entry.getAttribute("class") == "footnote")
      entriesToRemove.push(entry);
  }
  for (i = 0; i < entriesToRemove.length; i++) {
    noteholder.removeChild(entriesToRemove[i]);
  }

  // Rebuild footnote entries.
  var cont = document.getElementById("content");
  var spans = cont.getElementsByTagName("span");
  var refs = {};
  var n = 0;
  for (i=0; i<spans.length; i++) {
    if (spans[i].className == "footnote") {
      n++;
      var note = spans[i].getAttribute("data-note");
      if (!note) {
        // Use [\s\S] in place of . so multi-line matches work.
        // Because JavaScript has no s (dotall) regex flag.
        note = spans[i].innerHTML.match(/\s*\[([\s\S]*)]\s*/)[1];
        spans[i].innerHTML =
          "[<a id='_footnoteref_" + n + "' href='#_footnote_" + n +
          "' title='View footnote' class='footnote'>" + n + "</a>]";
        spans[i].setAttribute("data-note", note);
      }
      noteholder.innerHTML +=
        "<div class='footnote' id='_footnote_" + n + "'>" +
        "<a href='#_footnoteref_" + n + "' title='Return to text'>" +
        n + "</a>. " + note + "</div>";
      var id =spans[i].getAttribute("id");
      if (id != null) refs["#"+id] = n;
    }
  }
  if (n == 0)
    noteholder.parentNode.removeChild(noteholder);
  else {
    // Process footnoterefs.
    for (i=0; i<spans.length; i++) {
      if (spans[i].className == "footnoteref") {
        var href = spans[i].getElementsByTagName("a")[0].getAttribute("href");
        href = href.match(/#.*/)[0];  // Because IE return full URL.
        n = refs[href];
        spans[i].innerHTML =
          "[<a href='#_footnote_" + n +
          "' title='View footnote' class='footnote'>" + n + "</a>]";
      }
    }
  }
},

install: function(toclevels) {
  var timerId;

  function reinstall() {
    asciidoc.footnotes();
    if (toclevels) {
      asciidoc.toc(toclevels);
    }
  }

  function reinstallAndRemoveTimer() {
    clearInterval(timerId);
    reinstall();
  }

  timerId = setInterval(reinstall, 500);
  if (document.addEventListener)
    document.addEventListener("DOMContentLoaded", reinstallAndRemoveTimer, false);
  else
    window.onload = reinstallAndRemoveTimer;
}

}
asciidoc.install(3);
/*]]>*/
</script>
</head>
<body class="article">
<div id="header">
<h1>Java Packaging HOWTO</h1>
<div id="toc">
  <div id="toctitle">Table of Contents</div>
  <noscript><p><b>JavaScript must be enabled in your browser to display the table of contents.</b></p></noscript>
</div>
</div>
<div id="content">
<div id="preamble">
<div class="sectionbody">
<div class="paragraph"><p>v4.0.1, 2014-06-18</p></div>
<div class="paragraph"><p>The authors of this document are:</p></div>
<div class="ulist"><ul>
<li>
<p>
Mikolaj Izdebski, Red Hat
</p>
</li>
<li>
<p>
Nicolas Mailhot, JPackage Project
</p>
</li>
<li>
<p>
Stanislav Ochotnicky, Red Hat
</p>
</li>
<li>
<p>
Ville Skyttä, JPackage Project
</p>
</li>
<li>
<p>
Michal Srb, Red Hat
</p>
</li>
</ul></div>
<div class="paragraph"><p>This document is free software; see the
<a href="https://git.fedorahosted.org/cgit/javapackages.git/plain/LICENSE">license</a>
for terms of use, distribution and/or modification.</p></div>
<div class="paragraph"><p>The source code for this document is available in
<a href="https://git.fedorahosted.org/cgit/javapackages.git">git repository</a>.
Instructions for building it from sources are available in
<a href="https://git.fedorahosted.org/cgit/javapackages.git/plain/doc/README">README
file</a>.</p></div>
<div class="paragraph"><p>This document is developed as part of Javapackages community project,
which welcomes new contributors.  Requests and comments related to
this document should be
<a href="http://bugzilla.redhat.com/enter_bug.cgi?product=fedora&amp;component=javapackages-tools">reported</a>
at <a href="https://bugzilla.redhat.com/">Red Hat Bugzilla</a>.</p></div>
<div class="paragraph"><p>Before contributing please read the
<a href="https://git.fedorahosted.org/cgit/javapackages.git/plain/doc/README">README
file</a>, which among other things includes basic rules which should be
followed when working on this document.  You can send patches to
<a href="https://bugzilla.redhat.com/">Red Hat Bugzilla</a>.  They should be in git
format and should be prepared against <span class="monospaced">master</span> branch in git.
Alternatively you can also send pull requests at
<a href="https://github.com/mizdebsk/javapackages">Javapackages Github mirror</a>.</p></div>
</div>
</div>
<div class="sect1">
<h2 id="_abstract">Abstract</h2>
<div class="sectionbody">
<div class="paragraph"><p>This document aims to help developers create and maintain Java packages in
Fedora. It <strong>does not</strong> supersede or replace
<a href="https://fedoraproject.org/wiki/Packaging:Java">Java Packaging Guidelines</a>,
but rather aims to document tools and techniques used for packaging Java
software on Fedora.</p></div>
</div>
</div>
<div class="sect1">
<h2 id="_introduction">1. Introduction</h2>
<div class="sectionbody">
<div class="paragraph"><p>Clean Java packaging has historically been a daunting task.  Lack of
any standard addressing the physical location of files on the system
combined with the common use of licensing terms that only allow free
redistribution of key components as a part of a greater ensemble has
let to the systematic release of self-sufficient applications with
built-in copies of external components.</p></div>
<div class="paragraph"><p>As a consequence applications are only tested with the versions of the
components they bundle, a complete Java system suffers from endless
duplication of the same modules, and integrating multiple parts can be
a nightmare since they are bound to depend on the same elements - only
with different and subtly incompatible versions (different
requirements, different bugs).  Any security or compatibility upgrade
must be performed for each of those duplicated elements.</p></div>
<div class="paragraph"><p>This problem is compounded by the current practice of folding
extensions in the JVM itself after a while; an element that
could safely be embedded in a application will suddenly conflict with
a JVM part and cause subtle failures.</p></div>
<div class="paragraph"><p>It is not surprising then that complex Java systems tend to fossilize
very quickly, with the cost of maintaining dependencies current
growing too high so fast people basically give up on it.</p></div>
<div class="paragraph"><p>This situation is incompatible with typical fast-evolving Linux
platform.  To attain the aim of user- and administrator-friendly RPM
packaging of Java applications a custom infrastructure and strict
packaging rules had to be evolved.</p></div>
<div class="sect2">
<h3 id="_basic_introduction_to_packaging_reasons_problems_rationale">1.1. Basic introduction to packaging, reasons, problems, rationale</h3>
<div class="paragraph"><p>This section includes basic introduction to Java packaging world to people
coming from different backgrounds. Goal is to understand language of all groups
involved. If you are a Java developer coming into contact with RPM packaging for
the first time start reading <a href="#XFor_Devs">Java developer</a> section. On the
other hand if you are coming from RPM packaging background an
<a href="#XFor_Packagers">introduction to Java world</a> is probably a better starting
point.</p></div>
<div class="paragraph"><p>It should be noted that especially in this section we might sacrifice
correctness for simplicity.</p></div>
</div>
<div class="sect2">
<h3 id="XFor_Packagers">1.2. For Packagers</h3>
<div class="paragraph"><p>Java is a programming language which is usually compiled into bytecode for JVM
(Java Virtual Machine). For more details about the JVM and bytecode
specification see
<a href="http://docs.oracle.com/javase/specs/jvms/se7/html/index.html">JVM
documentation</a>.</p></div>
<div class="sect3">
<h4 id="_example_java_project">1.2.1. Example Java Project</h4>
<div class="paragraph"><p>To better illustrate various parts of Java packaging we will dissect simple Java
&#8220;Hello world&#8221; application. Java sources are usually organized using directory
hierarchies. Shared directory hierarchy creates a namespace called <span class="monospaced">package</span> in
Java terminology. To understand naming mechanisms of Java <span class="monospaced">packages</span> see
<a href="http://docs.oracle.com/javase/tutorial/java/package/namingpkgs.html">Java
package naming conventions</a>.</p></div>
<div class="paragraph"><p>Let&#8217;s create a simple hello world application that will execute following steps
when run:</p></div>
<div class="olist arabic"><ol class="arabic">
<li>
<p>
Ask for a name
</p>
</li>
<li>
<p>
Print out &#8220;Hello World from&#8221; and the name from previous step
</p>
</li>
</ol></div>
<div class="paragraph"><p>To illustrate certain points we artificially complicate things by creating:</p></div>
<div class="ulist"><ul>
<li>
<p>
<span class="monospaced">Input</span> class used only for input of text from terminal
</p>
</li>
<li>
<p>
<span class="monospaced">Output</span> class used only for output on terminal
</p>
</li>
<li>
<p>
<span class="monospaced">HelloWorldApp</span> class used as main application
</p>
</li>
</ul></div>
<div class="listingblock">
<div class="title">Directory listing of example project</div>
<div class="content"></div></div>
<div class="paragraph"><p>In this project all packages are under <span class="monospaced">src/</span> directory hierarchy.</p></div>
<div class="listingblock">
<div class="title">HelloWorld.java listing</div>
<div class="content"></div></div>
<div class="listingblock">
<div class="title">Java packages</div>
<div class="content"></div></div>
<div class="paragraph"><p>Although the directory structure of our package is hierarchical, there
is no real parent-child relationship between packages. Each package is
therefore seen as independent.
Above example makes use of three separate packages:</p></div>
<div class="ulist"><ul>
<li>
<p>
<span class="monospaced">org.fedoraproject.helloworld.input</span>
</p>
</li>
<li>
<p>
<span class="monospaced">org.fedoraproject.helloworld.output</span>
</p>
</li>
<li>
<p>
<span class="monospaced">org.fedoraproject.helloworld</span>
</p>
</li>
</ul></div>
<div class="paragraph"><p>Environment setup consists of two main parts:</p></div>
<div class="ulist"><ul>
<li>
<p>
Telling JVM which Java class contains <span class="monospaced">main()</span> method
</p>
</li>
<li>
<p>
Adding required JAR files on JVM classpath
</p>
</li>
</ul></div>
<div class="paragraph"><div class="title">Compiling our project</div><p>The sample project can be compiled to a bytecode by Java compiler. Java
compiler can be typically invoked from command line by command <span class="monospaced">javac</span>.</p></div>
<div class="listingblock">
<div class="content"></div></div>
<div class="paragraph"><p>For every <span class="monospaced">.java</span> file corresponding <span class="monospaced">.class</span> file will be created. The
<span class="monospaced">.class</span> files contain Java bytecode which is meant to be executed on
JVM.</p></div>
<div class="paragraph"><p>One could put invocation of <span class="monospaced">javac</span> to Makefile and simplify the
compilation a bit. It might be sufficient for such a simple project, but
it would quickly become hard to build more complex projects with this
approach. Java world knows several high-level build systems which can
highly simplify building of Java projects. Among the others, probably
most known are <a href="http://maven.apache.org/">Apache Maven</a>,
<a href="http://ant.apache.org/">Apache Ant</a> and <a href="http://www.gradle.org/">Gradle</a>.</p></div>
<div class="admonitionblock">
<table><tr>
<td class="icon">
<img src="./images/icons/tip.png" alt="Tip">
</td>
<td class="content">
<div class="paragraph"><p>See also <a href="#maven">Maven</a> and <a href="#ant">Ant</a> sections.</p></div>
</td>
</tr></table>
</div>
<div class="paragraph"><div class="title">JAR files</div><p>Having our application split across many <span class="monospaced">.class</span> files wouldn&#8217;t be very
practical, so those <span class="monospaced">.class</span> files are assembled into ZIP files with
specific layout called JAR files. Most commonly these special ZIP files
have <span class="monospaced">.jar</span> suffix, but other variations exist (<span class="monospaced">.war</span>, <span class="monospaced">.ear</span>). They
contain:</p></div>
<div class="ulist"><ul>
<li>
<p>
Compiled bytecode of our project
</p>
</li>
<li>
<p>
Additional metadata stored in <span class="monospaced">META-INF/MANIFEST.MF</span> file
</p>
</li>
<li>
<p>
Resource files such as images or localisation data
</p>
</li>
<li>
<p>
Optionaly the source code of our project (called source JAR then)
</p>
</li>
</ul></div>
<div class="paragraph"><p>They can also contain additional bundled software which is something
we don&#8217;t want to have in packages. You can inspect the contents of given
JAR file by extracting it. That can be done with following command:</p></div>
<div class="listingblock">
<div class="content"></div></div>
<div class="paragraph"><p>The detailed description of JAR file format is in the
<a href="http://docs.oracle.com/javase/7/docs/technotes/guides/jar/jar.html">JAR File
Specification</a>.</p></div>
<div class="paragraph"><div class="title">Classpath</div><p>The classpath is a way of telling JVM where to look for user classes
and 3rd party libraries. By default, only current directory is searched,
all other locations need to be specified explicitly by setting up
CLASSPATH environment variable, or via <span class="monospaced">-cp</span> (<span class="monospaced">-classpath</span>) option of a
Java Virtual Machine.</p></div>
<div class="listingblock">
<div class="title">Setting the classpath</div>
<div class="content"></div></div>
<div class="paragraph"><p>Please note that two JAR files are separated by colon in a classpath
definition.</p></div>
<div class="admonitionblock">
<table><tr>
<td class="icon">
<img src="./images/icons/tip.png" alt="Tip">
</td>
<td class="content">
<div class="paragraph"><p>See
<a href="http://docs.oracle.com/javase/7/docs/technotes/tools/windows/classpath.html">official
documentation</a> for more information about classpath.</p></div>
</td>
</tr></table>
</div>
<div class="paragraph"><div class="title">Wrapper scripts</div><p>Classic compiled applications use dynamic linker to find dependencies (linked
libraries), Python interpreter has predefined directories where it searches for
imported modules. JVM itself has no embedded knowledge of installation paths and
thus no automatic way to resolve dependencies of Java projects. This means that
all Java applications have to use wrapper shell scripts to setup the environment
before invoking the JVM and running the application itself. Note that this is
not necessary for libraries.</p></div>
</div>
<div class="sect3">
<h4 id="_build_system_identification">1.2.2. Build System Identification</h4>
<div class="paragraph"><p>Build system used by upstream can be usually identified by looking at
their configuration files, which reside in project directory structure,
usually in its root or in specialized directories with names such as
<span class="monospaced">build</span> or <span class="monospaced">make</span>.</p></div>
<div class="paragraph"><div class="title">Maven</div><p>Build managed by Apache Maven is configured by an XML file that is by
default named <span class="monospaced">pom.xml</span>. In its simpler form it usually looks like this:</p></div>
<div class="listingblock">
<div class="content"></div></div>
<div class="paragraph"><p>It describes project&#8217;s build process in a declarative way, without
explicitly specifying exact steps needed to compile sources and assemble
pieces together. It also specifies project&#8217;s dependencies which are
usually the main point of interest for packagers. Other important
feature of Maven that packagers should know about are plugins. Plugins
extend Maven with some particular functionality, but unfortunately some
of them may get in the way of packaging and need to be altered or
removed. There are RPM macros provided to facilitate modifying Maven
dependencies and plugins.</p></div>
<div class="paragraph"><div class="title">Ant</div><p>Apache Ant is also configured by an XML file. It is by convention named
<span class="monospaced">build.xml</span> and in its simple form it looks like this:</p></div>
<div class="listingblock">
<div class="content"></div></div>
<div class="paragraph"><p>Ant build file consists mostly of targets, which are collections of
steps needed to accomplish intended task. They usually depend on each
other and are generally similar to Makefile targets. Available targets
can be listed by invoking <span class="monospaced">ant -p</span> in project directory containing
<span class="monospaced">build.xml</span> file. If the file is named differently than <span class="monospaced">build.xml</span> you
have to tell Ant which file should be used by using <span class="monospaced">-f</span> option with the
name of the actual build file.</p></div>
<div class="paragraph"><p>Some projects that use Apache Ant also use Apache Ivy to simplify
dependency handling. Ivy is capable of resolving and downloading
artifacts from Maven repositories which are declaratively described in
XML. Project usually contains one or more <span class="monospaced">ivy.xml</span> files specifying the
module Maven coordinates and its dependecies. Ivy can also be used
directly from Ant build files. To detect whether the project you wish to
package is using Apache Ivy, look for files named <span class="monospaced">ivy.xml</span> or nodes in
the <span class="monospaced">ivy</span> namespace in project&#8217;s build file.</p></div>
<div class="paragraph"><div class="title">Gradle</div><p>Gradle is configured by a script written in Groovy (dynamic language
built on top of JVM and extending Java&#8217;s syntax). It&#8217;s configuration
file is <span class="monospaced">build.gradle</span>.</p></div>
<div class="listingblock">
<div class="content"></div></div>
<div class="paragraph"><div class="title">Make</div><p>While unlikely, it&#8217;s still possible that you encounter a project whose
build is managed by plain old Makefiles. They contain a list of targets
which consist of commands (marked with tab at the begining of line) and
are invoked by <span class="monospaced">make</span> <em>target</em> or simply <span class="monospaced">make</span> to run the default
target.</p></div>
</div>
<div class="sect3">
<h4 id="_quiz_for_packagers">1.2.3. Quiz for Packagers</h4>
<div class="paragraph"><p>At this point you should have enough knowledge about Java to start
packaging. If you are not able to answer following questions return back to
previous sections or ask experienced packagers for different explanations of
given topics.</p></div>
<div class="olist arabic"><ol class="arabic">
<li>
<p>
What is the difference between JVM and Java?
</p>
</li>
<li>
<p>
What is a CLASSPATH environment variable and how can you use it?
</p>
</li>
<li>
<p>
Name two typical Java build systems and how you can identify which one is being used
</p>
</li>
<li>
<p>
What is the difference between <span class="monospaced">java</span> and <span class="monospaced">javac</span> comands?
</p>
</li>
<li>
<p>
What are contents of a typical <span class="monospaced">JAR</span> file?
</p>
</li>
<li>
<p>
What is a pom.xml file and what information it contains?
</p>
</li>
<li>
<p>
How would you handle packaging software that contains <span class="monospaced">lib/junit4.jar</span> inside
   source tarball?
</p>
</li>
<li>
<p>
Name at least three methods for bundling code in Java projects
</p>
</li>
</ol></div>
</div>
</div>
<div class="sect2">
<h3 id="XFor_Devs">1.3. For Java Developers</h3>
<div class="paragraph"><p>Packaging Java software has specifics which we will try to cover in this section
aimed at Java developers who are already familiar with Java language, JVM,
classpath handling, Maven, pom.xml file structure and dependencies.</p></div>
<div class="paragraph"><p>Instead we will focus on basic packaging tools and relationships between Java
and RPM world. One of the most important questions is: What is the reason to
package software in RPM (or other distribution-specific formats). There are
several reasons for it, among others:</p></div>
<div class="ulist"><ul>
<li>
<p>
Unified way of installation of software for users of distribution regardless
    of upstream projects
</p>
</li>
<li>
<p>
Verification of authenticity of software packages by signing them
</p>
</li>
<li>
<p>
Simplified software updates
</p>
</li>
<li>
<p>
Automatic handling of dependencies for users
</p>
</li>
<li>
<p>
Common filesystem layout across distribution enforced by packaging standards
</p>
</li>
<li>
<p>
Ability to administer, monitor and query packages installed on several
    machines through unified interfaces
</p>
</li>
<li>
<p>
Distribution of additional metadata with the software itself such as
    licenses used, homepage for the project, changelogs and other information
    that users or administrators can find useful
</p>
</li>
</ul></div>
<div class="sect3">
<h4 id="_example_rpm_project">1.3.1. Example RPM Project</h4>
<div class="paragraph"><p>RPM uses <span class="monospaced">spec</span> files as recipes for building software packages.  We
will use it to package example project created in previous section. If
you didn&#8217;t read it you don&#8217;t need to; the file listing is available here
and the rest is not necessary for this section.</p></div>
<div class="listingblock">
<div class="title">Directory listing</div>
<div class="content"></div></div>
<div class="paragraph"><p>We packed the project directory into file <span class="monospaced">helloworld.tar.gz</span>.</p></div>
<div class="listingblock">
<div class="title">Example spec file</div>
<div class="content"></div></div>
<div class="paragraph"><p>RPM <span class="monospaced">spec</span> files contain several basic sections:</p></div>
<div class="dlist"><dl>
<dt class="hdlist1">
Header, which contains: 
</dt>
<dd>
<div class="ulist"><ul>
<li>
<p>
Package metadata such as its name, version, release,
     license&#8230;
</p>
</li>
<li>
<p>
A <span class="monospaced">Summary</span> with basic one-line summary of package contents
</p>
</li>
<li>
<p>
Package source URLs denoted with <span class="monospaced">Source0</span> to <span class="monospaced">SourceN</span> directives
</p>
<div class="ulist"><ul>
<li>
<p>
Source files can then be referenced by <span class="monospaced">%SOURCE0</span> to
      <span class="monospaced">%SOURCEn</span>, which expand to actual paths to given files
</p>
</li>
<li>
<p>
In practice, the source URL shouldn&#8217;t point to a file in our
      filesystem, but to an upstream release on the web
</p>
</li>
</ul></div>
</li>
<li>
<p>
Patches - using <span class="monospaced">Patch0</span> to <span class="monospaced">PatchN</span>
</p>
</li>
<li>
<p>
Project dependencies
</p>
<div class="ulist"><ul>
<li>
<p>
Build dependencies specified by <span class="monospaced">BuildRequires</span>, which need to be
      determined manually.
</p>
</li>
<li>
<p>
Run time dependencies will be detected automatically. If it fails,
      you have to specify them with <span class="monospaced">Requires</span>.
</p>
</li>
<li>
<p>
More information on this topic can be found in
      <a href="#dependency_handling">Dependency handling</a> section.
</p>
</li>
</ul></div>
</li>
</ul></div>
</dd>
<dt class="hdlist1">
Description
</dt>
<dd>
<div class="ulist"><ul>
<li>
<p>
Few sentences about the project and its uses. It will be displayed
     by package management software.
</p>
</li>
</ul></div>
</dd>
<dt class="hdlist1">
Prep section
</dt>
<dd>
<div class="ulist"><ul>
<li>
<p>
Unpacks the sources using <span class="monospaced">setup -q</span> or manually if needed
</p>
</li>
<li>
<p>
If a source file doesn&#8217;t need to be extracted, it can be copied
     to build directory by <span class="monospaced">cp -p %SOURCE0 .</span>
</p>
</li>
<li>
<p>
Apply patches with <span class="monospaced">%patchX</span>, where X is the number of patch you
     want to apply. (You usually need the patch index, so it would be:
     <span class="monospaced">%patch0 -p1</span>)
</p>
</li>
</ul></div>
</dd>
<dt class="hdlist1">
Build section
</dt>
<dd>
<div class="ulist"><ul>
<li>
<p>
Contains project compilation instructions. Usually consists of
     calling the projects build system such as Ant, Maven or Make.
</p>
</li>
</ul></div>
</dd>
<dt class="hdlist1">
Optional <span class="monospaced">%check</span> section
</dt>
<dd>
<div class="ulist"><ul>
<li>
<p>
Runs projects integration tests. Unit test are usually run in
     <span class="monospaced">%build</span> section, so if there are no integration tests available,
     this section is omitted
</p>
</li>
</ul></div>
</dd>
<dt class="hdlist1">
Install section
</dt>
<dd>
<div class="ulist"><ul>
<li>
<p>
Copies built files that are supposed to be installed into
     <span class="monospaced">%{buildroot}</span> directory, which represents target filesystem&#8217;s root
</p>
</li>
</ul></div>
</dd>
<dt class="hdlist1">
Files section
</dt>
<dd>
<div class="ulist"><ul>
<li>
<p>
Lists all files, that should be installed from <span class="monospaced">%{buildroot}</span> to
     target system.
</p>
</li>
<li>
<p>
Documentation files are prefixed by <span class="monospaced">%doc</span> and are
     taken from build directory instead of buildroot
</p>
</li>
<li>
<p>
Directories that this package should own are prefixed with <span class="monospaced">%dir</span>
</p>
</li>
</ul></div>
</dd>
<dt class="hdlist1">
Changelog
</dt>
<dd>
<div class="ulist"><ul>
<li>
<p>
Contains changes to this spec file (not upstream)
</p>
</li>
<li>
<p>
Has prescribed format. To prevent mistakes in format, it is
     advised to use tool such as <span class="monospaced">rpmdev-bumpspec</span> from package rpmdevtools to
     append new changelog entries instead of editing it by hand
</p>
</li>
</ul></div>
</dd>
</dl></div>
<div class="paragraph"><p>To build RPM from <a href="rpm_project/helloworld.spec">this <span class="monospaced">spec</span> file</a> save it in
your current directory and run <span class="monospaced">rpmbuild</span>:</p></div>
<div class="listingblock">
<div class="content"></div></div>
<div class="paragraph"><p>If everything worked OK, this should produce RPM file
<span class="monospaced">~/rpmbuild/RPMS/x86_64/helloworld-1.0-1.fc18.x86_64.rpm</span>. You can use
<span class="monospaced">rpm -i</span> or <span class="monospaced">yum localinstall</span> commands to install this package and it
will add <span class="monospaced">/usr/share/java/helloworld.jar</span> and <span class="monospaced">/usr/bin/helloworld</span>
wrapper script to your system. Please note that this specfile is
simplified and lacks some additional parts, such as license
installation.</p></div>
<div class="admonitionblock">
<table><tr>
<td class="icon">
<img src="./images/icons/note.png" alt="Note">
</td>
<td class="content">
<div class="paragraph"><p>Paths and filenames might be slightly different depending on your architecture
and distribution. Output of the commands will tell you exact paths</p></div>
</td>
</tr></table>
</div>
<div class="paragraph"><p>As you can see to build RPM files you can use <span class="monospaced">rpmbuild</span> command. It has several
other options, which we will cover later on.</p></div>
<div class="paragraph"><p>Except building binary RPMs (<span class="monospaced">-bb</span>), <span class="monospaced">rpmbuild</span> can also be told to:</p></div>
<div class="ulist"><ul>
<li>
<p>
build only source RPMs (SRPMs), the packages containing source files
   which can be later build to RPMs (option <span class="monospaced">-bs</span>)
</p>
</li>
<li>
<p>
build all, both binary and source RPMs (option <span class="monospaced">-ba</span>)
</p>
</li>
</ul></div>
<div class="paragraph"><p>See <span class="monospaced">rpmbuild</span>'s manual page for all available options.</p></div>
</div>
<div class="sect3">
<h4 id="querying_repositories">1.3.2. Querying repositories</h4>
<div class="paragraph"><p>Fedora comes with several useful tools which can provide great
assistance in getting information from RPM repositories.</p></div>
<div class="paragraph"><p><span class="monospaced">repoquery</span> is a tool for querying information from YUM repositories.
Maintainer of Java packages might typically query the repository for
information like "which package contains Maven artifact
<span class="monospaced">groupId:artifactId</span>".</p></div>
<div class="listingblock">
<div class="title">Find out which package provides given artifact</div>
<div class="content"></div></div>
<div class="paragraph"><p>The example above shows that one can get to <span class="monospaced">commons-io:commons-io</span>
artifact by installing <span class="monospaced">apache-commons-io</span> package.</p></div>
<div class="paragraph"><p>By default, repoquery uses all enabled repositories in YUM
configuration, but it is possible to explicitly specify any other
repository. For example following command will query only Rawhide
repository:</p></div>
<div class="listingblock">
<div class="content"></div></div>
<div class="paragraph"><p>Sometimes it may be useful to just list all the artifacts provided by
given package:</p></div>
<div class="listingblock">
<div class="content"></div></div>
<div class="paragraph"><p>Output above means that package <span class="monospaced">apache-commons-io</span> provides two Maven
artifacts: previously mentioned <span class="monospaced">commons-io:commons-io</span> and
<span class="monospaced">org.apache.commons:commons-io</span>. In this case the second one is just an
alias for same JAR file. See section about <a href="#aliases">artifact aliases</a>
for more information on this topic.</p></div>
<div class="paragraph"><p>Another useful tool is <span class="monospaced">rpm</span>. It can do a lot of stuff, but most
importantly it can replace <span class="monospaced">repoquery</span> if one only needs to query local
RPM database. Only installed packages, or local <span class="monospaced">.rpm</span> files, can be
queried with this tool.</p></div>
<div class="paragraph"><p>Common use case could be checking which Maven artifacts provide locally
built packages.</p></div>
<div class="listingblock">
<div class="content"></div></div>
</div>
<div class="sect3">
<h4 id="_quiz_for_java_developers">1.3.3. Quiz for Java Developers</h4>
<div class="olist arabic"><ol class="arabic">
<li>
<p>
How would you build a binary RPM if you were given a source RPM?
</p>
</li>
<li>
<p>
What is most common content of Source0 <span class="monospaced">spec</span> file tag?
</p>
</li>
<li>
<p>
What is the difference between <span class="monospaced">Version</span> and <span class="monospaced">Release</span> tags?
</p>
</li>
<li>
<p>
How would you apply a patch in RPM?
</p>
</li>
<li>
<p>
Where on filesystem should JAR files go?
</p>
</li>
<li>
<p>
What is the format of RPM changelog or what tool would you use to produce it?
</p>
</li>
<li>
<p>
How would you install an application that needs certain layout (think
   ANT_HOME) while honoring distribution filesystem layout guidelines?
</p>
</li>
<li>
<p>
How would you generate script for running a application with main class
   org.project.MainClass which depends on commons-lang jar?
</p>
</li>
</ol></div>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_java_specifics_in_fedora_for_users_and_developers">2. Java Specifics in Fedora for Users and Developers</h2>
<div class="sectionbody">
<div class="paragraph"><p>This section contains information about default Java implementation in
Fedora, switching between different Java runtime environments and about
few useful tools which can be used during packaging/development.</p></div>
<div class="sect2">
<h3 id="openjdk">2.1. Java implementation in Fedora</h3>
<div class="paragraph"><p>Fedora ships with reference implementation of Java Standard Edition 7
called <a href="http://openjdk.java.net/OpenJDK">OpenJDK</a>. OpenJDK provides Java
Runtime Environment for Java applications and set of development tools
for Java developers.</p></div>
<div class="paragraph"><p>From users point of view, <span class="monospaced">java</span> command is probably most interesting.
It&#8217;s a Java application launcher which spawns Java Virtual Machine
(JVM), loads specified <span class="monospaced">.class</span> file and executes its main method.</p></div>
<div class="paragraph"><p>Here is an example how to run sample Java project from section 1.1.1:</p></div>
<div class="listingblock">
<div class="content"></div></div>
<div class="paragraph"><p>OpenJDK provides a lot of interesting tools for Java developers:</p></div>
<div class="ulist"><ul>
<li>
<p>
<span class="monospaced">javac</span> is a Java compiler which translates source files
to Java bytecode, which can be later interpreted by JVM.
</p>
</li>
<li>
<p>
<span class="monospaced">jdb</span> is a simple command-line debugger for Java applications.
</p>
</li>
<li>
<p>
<span class="monospaced">javadoc</span> is a tool for generating Javadoc documentation.
</p>
</li>
<li>
<p>
<span class="monospaced">javap</span> can be used for disassembling Java class files.
</p>
</li>
</ul></div>
<div class="sect3">
<h4 id="_switching_between_different_java_implementations">2.1.1. Switching between different Java implementations</h4>
<div class="paragraph"><p>Users and developers may want to have multiple Java environments
installed at the same time. It is possible in Fedora, but only one of
them can be default Java environment in system. Fedora uses
<span class="monospaced">alternatives</span> for switching between different installed JREs/JDKs.</p></div>
<div class="listingblock">
<div class="content monospaced">
<pre># alternatives --config java

There are 3 programs which provide 'java'.

  Selection    Command
  -----------------------------------------------
   1           /usr/lib/jvm/jre-1.5.0-gcj/bin/java
*+ 2           /usr/lib/jvm/java-1.7.0-openjdk-1.7.0.60-2.4.3.1.fc21.x86_64/jre/bin/java
   3           /usr/lib/jvm/jre-1.8.0-openjdk.x86_64/bin/java

Enter to keep the current selection[+], or type selection number:</pre>
</div></div>
<div class="paragraph"><p>Example above shows how to chose default Java environments from all
environments currently available on the system. All Java applications
will start using this chosen environment from now on.</p></div>
<div class="admonitionblock">
<table><tr>
<td class="icon">
<img src="./images/icons/tip.png" alt="Tip">
</td>
<td class="content">
<div class="paragraph"><p>See <span class="monospaced">man alternatives</span> for more information on how to use
<span class="monospaced">alternatives</span>.</p></div>
</td>
</tr></table>
</div>
<div class="paragraph"><p>Developers may want to use Java compiler from different JDK. This can be
also achieved with <span class="monospaced">alternatives --config javac</span>.</p></div>
</div>
</div>
<div class="sect2">
<h3 id="_building_classpath_with_span_class_monospaced_build_classpath_span">2.2. Building classpath with <span class="monospaced">build-classpath</span></h3>
<div class="paragraph"><p>Most of the Java application needs to specify classpath in order to work
correctly. Fedora contains several tools which make working with
classpaths easier.</p></div>
<div class="paragraph"><p><span class="monospaced">build-classpath</span> - this tool takes JAR filenames or artifact
coordinates as arguments and translates them to classpath-like string.
See following example:</p></div>
<div class="listingblock">
<div class="content"></div></div>
<div class="paragraph"><p><span class="monospaced">log4j</span> corresponds to <span class="monospaced">log4j.jar</span> stored in <span class="monospaced">%{_javadir}</span>. If the JAR
file is stored in subdirectory under <span class="monospaced">%{_javadir}</span>, it&#8217;s neccessary to
pass <span class="monospaced">subdirectory/jarname</span> as an argument to <span class="monospaced">build-classpath</span>.
Example:</p></div>
<div class="listingblock">
<div class="content"></div></div>
</div>
<div class="sect2">
<h3 id="_building_jar_repository_with_span_class_monospaced_build_jar_repository_span">2.3. Building JAR repository with <span class="monospaced">build-jar-repository</span></h3>
<div class="paragraph"><p>Another tool is <span class="monospaced">build-jar-repository</span>. It can fill specified directory
with symbolic/hard links to specified JAR files.Similarly to
<span class="monospaced">build-classpath</span>, JARs can be identified by their names or artifact
coordintes.</p></div>
<div class="listingblock">
<div class="content"></div></div>
<div class="paragraph"><p>Similar command <span class="monospaced">rebuild-jar-repository</span> can be used to rebuild JAR
repository previously built by <span class="monospaced">build-jar-repository</span>. See <span class="monospaced">man
rebuild-jar-repository</span> for more information.</p></div>
<div class="paragraph"><p><span class="monospaced">build-classpath-directory</span> is a small tool which can be used to build
classpath string from specified directory.</p></div>
<div class="listingblock">
<div class="content"></div></div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_java_specifics_in_fedora_for_packagers">3. Java Specifics in Fedora for Packagers</h2>
<div class="sectionbody">
<div class="paragraph"><p>WORK IN PROGRESS
mizdebsk, 25 Oct 2013</p></div>
<div class="sect2">
<h3 id="_directory_layout">3.1. Directory Layout</h3>
<div class="paragraph"><p>This section describes most of directories used for Java packaging.
Each directory is named in RPM macro form, which shows how it should
be used in RPM spec files.  Symbolic name is followed by usual macro
expansion (i.e. physical directory location in the file system) and
short description.</p></div>
<div class="dlist glossary"><div class="title">Directories commonly used by regular packages</div><dl>
<dt>
<strong><span class="monospaced">%{_javadir}</span></strong>&#8201;&#8212;&#8201;<span class="monospaced">/usr/share/java</span>
</dt>
<dd>
<p>
    Directory that holds all JAR files that do not contain or use
    native code and do not depend on a particular Java standard
    version.  JAR files can either be placed directly in this
    directory or one of its subdirectories.  Often packages create
    their own subdirectories there, in this case subdirectory name
    should match package name.
</p>
</dd>
<dt>
<strong><span class="monospaced">%{_jnidir}</span></strong>&#8201;&#8212;&#8201;<span class="monospaced">/usr/lib/java</span>
</dt>
<dd>
<p>
    Directory where architecture-specific JAR files are installed.  In
    particular JAR files containing or using native code (Java Native
    Interface, NI) should be installed.
</p>
</dd>
<dt>
<strong><span class="monospaced">%{_javadocdir}</span></strong>&#8201;&#8212;&#8201;<span class="monospaced">/usr/share/javadoc</span>
</dt>
<dd>
<p>
    Root directory where all Java API documentation (Javadoc) is
    installed.  Each source package usually creates a single
    subdirectory containing aggregated Javadocs for all binary
    packages it produces.
</p>
</dd>
<dt>
<strong><span class="monospaced">%{_mavenpomdir}</span></strong>&#8201;&#8212;&#8201;<span class="monospaced">/usr/share/maven-poms</span>
</dt>
<dd>
<p>
    Directory where Project Object Model (POM) files used by Apache
    Maven are installed.  Each POM must have name that strictly
    corresponds to JAR file in <span class="monospaced">%{_javadir}</span> or <span class="monospaced">%{_jnidir}</span>.
</p>
</dd>
</dl></div>
<div class="dlist glossary"><div class="title">Other directories</div><dl>
<dt>
<strong><span class="monospaced">%{_jvmdir}</span></strong>&#8201;&#8212;&#8201;<span class="monospaced">/usr/lib/jvm</span>
</dt>
<dd>
<p>
    Root directory where different Java Virtual Machines (JVM) are
    installed.  Each JVM creates a subdirectory, possibly with several
    alternative names implemented with symbolic links.  Directories
    prefixed with <span class="monospaced">java</span> contain Java Development Kit (JDK), while
    directories which names start with <span class="monospaced">jre</span> hold Java Runtime
    Environment (JRE).
</p>
</dd>
<dt>
<strong><span class="monospaced">%{_jvmsysconfdir}</span></strong>&#8201;&#8212;&#8201;<span class="monospaced">/etc/jvm</span>
</dt>
<dt>
<strong><span class="monospaced">%{_jvmcommonsysconfdir}</span></strong>&#8201;&#8212;&#8201;<span class="monospaced">/etc/jvm-common</span>
</dt>
<dd>
<p>
    Directories containing configuration files for Java Virtual
    Machines (JVM).
</p>
</dd>
<dt>
<strong><span class="monospaced">%{_jvmjardir}</span></strong>&#8201;&#8212;&#8201;<span class="monospaced">/usr/lib/jvm-exports</span>
</dt>
<dt>
<strong><span class="monospaced">%{_jvmprivdir}</span></strong>&#8201;&#8212;&#8201;<span class="monospaced">/usr/lib/jvm-private</span>
</dt>
<dt>
<strong><span class="monospaced">%{_jvmlibdir}</span></strong>&#8201;&#8212;&#8201;<span class="monospaced">/usr/lib/jvm</span>
</dt>
<dt>
<strong><span class="monospaced">%{_jvmdatadir}</span></strong>&#8201;&#8212;&#8201;<span class="monospaced">/usr/share/jvm</span>
</dt>
<dt>
<strong><span class="monospaced">%{_jvmcommonlibdir}</span></strong>&#8201;&#8212;&#8201;<span class="monospaced">/usr/lib/jvm-common</span>
</dt>
<dt>
<strong><span class="monospaced">%{_jvmcommondatadir}</span></strong>&#8201;&#8212;&#8201;<span class="monospaced">/usr/share/jvm-common</span>
</dt>
<dd>
<p>
    Directories containing implementation files of Java Virtual
    Machines (JVM).  Describing them in detail is out of scope for
    this document.  Purpose of each directory is commented briefly in
    <span class="monospaced">macros.jpackage</span> file in <span class="monospaced">/etc/rpm</span>.  More detailed description
    can be found in JPackage policy.
</p>
</dd>
<dt>
<strong><span class="monospaced">%{_javaconfdir}</span></strong>&#8201;&#8212;&#8201;<span class="monospaced">/etc/java</span>
</dt>
<dd>
<p>
    Directory containing Java configuration files.  In particular it
    contains main Java configuration file&#8201;&#8212;&#8201;<span class="monospaced">java.conf</span>.
</p>
</dd>
<dt>
<strong><span class="monospaced">%{_javadir}-ext</span></strong>&#8201;&#8212;&#8201;<span class="monospaced">/usr/share/java-ext</span>
</dt>
<dt>
<strong><span class="monospaced">%{_javadir}-</span><span class="monospaced"><em>x</em>.<em>y</em>.<em>z</em></span></strong>&#8201;&#8212;&#8201;<span class="monospaced">/usr/share/java-</span><span class="monospaced"><em>x</em>.<em>y</em>.<em>z</em></span>
</dt>
<dt>
<strong><span class="monospaced">%{_jnidir}-ext</span></strong>&#8201;&#8212;&#8201;<span class="monospaced">/usr/lib/java-ext</span>
</dt>
<dt>
<strong><span class="monospaced">%{_jnidir}-</span><span class="monospaced"><em>x</em>.<em>y</em>.<em>z</em></span></strong>&#8201;&#8212;&#8201;<span class="monospaced">/usr/lib/java-</span><span class="monospaced"><em>x</em>.<em>y</em>.<em>z</em></span>
</dt>
<dd>
<p>
    These directories are rarely used and are retained mostly for
    compatibility with JPackage project.  They are meant to contain
    JAR files that depend on particular Java standard version.  Note
    that such JARs can (and usually are) placed in <span class="monospaced">%{_javadir}</span> or
    <span class="monospaced">%{_jnidir}</span>.
</p>
</dd>
</dl></div>
</div>
<div class="sect2">
<h3 id="_jar_file_identification">3.2. JAR File Identification</h3>
<div class="paragraph"><p>Complex Java applications usually consist of multiple components.
Each component can have multiple implementations, called <em>artifacts</em>.
Artifacts in Java context are <em>usually</em> JAR files, but can also be WAR
files or any other kind of file.</p></div>
<div class="paragraph"><p>There are multiple incompatible ways of identifying (naming) Java
artifacts and each build system often encourages usage of specific
naming scheme.  This means that Linux distributions also need to allow
each artifact to be located using several different identifiers,
possible using different schemes.  On the other hand it is virtually
impossible to every naming scheme, so there are some simplifications.</p></div>
<div class="paragraph"><p>This chapter describes artifact different ways to identify and locate
artifacts in system repository.</p></div>
<div class="sect3">
<h4 id="_relative_paths">3.2.1. Relative paths</h4>
<div class="paragraph"><p>JAR artifacts are installed in one of standard
directory trees.  Usually this is either <span class="monospaced">%{_javadir}</span>
(<span class="monospaced">/usr/share/java</span>) or <span class="monospaced">%{_jnidir}</span> (<span class="monospaced">/usr/lib/java</span>).</p></div>
<div class="paragraph"><p>The simplest way of identifying artifacts is using their relative path
from one of standard locations.  All artifact can be identified this
way because each artifacts has a unique file name.  Each path
identifying artifact will be called <em>artifact path</em> in this document.</p></div>
<div class="paragraph"><p>To keep artifact paths simpler and more readable, extension can be
omitted if it is equal to <span class="monospaced">jar</span>.  For non-JAR artifacts extension
cannot be omitted and must be retained.</p></div>
<div class="paragraph"><p>Additionally, if artifact path points to a directory then it
represents all artifacts contained in this directory.  This allows a
whole set of related artifacts to be referenced easily by specifying
directory name containing all of them.</p></div>
<div class="paragraph"><p>If the same artifact path has valid expansions in two different root
directories then it is unspecified which artifacts will be located.</p></div>
</div>
<div class="sect3">
<h4 id="_artifact_specification">3.2.2. Artifact specification</h4>
<div class="paragraph"><p>As noted in previous section, every artifact can be uniquely identified
by its file path.  However this is not always the preferred way of
artifact identification.</p></div>
<div class="paragraph"><p>Modern Java build systems provide a way of identifying artifacts with
an abstract identifier, or more often a pair of identifiers.  The
first if usually called <strong>group ID</strong> or <strong>organization ID</strong> while the
second is just <strong>artifact ID</strong>.  This pair of identifiers will be called
<strong>artifact coordinates</strong> in this document.  Besides group ID and
artifact ID, artifact coordinates may also include other (optional)
information about artifact, such as <strong>extension</strong>, <strong>classifier</strong> or
<strong>version</strong>.</p></div>
<div class="paragraph"><p>In Linux distributions it&#8217;s important to stay close to upstreams
providing software being packaged, so the ability to identify
artifacts in the same way as upstream does is very important from the
point of view of packaging.  Every artifact can optionally be
identified by artifact coordinates assigned during package build.
Packages built with Maven automatically use this feature, but all
other packages, even these built with pure <span class="monospaced">javac</span>, can use this
feature too (see description of <span class="monospaced">%mvn_artifact</span> and
<span class="monospaced">%add_maven_depmap</span> macros).</p></div>
</div>
<div class="sect3">
<h4 id="aliases">3.2.3. Aliases</h4>
<div class="paragraph"><p>Aliases working in two ways:</p></div>
<div class="ulist"><ul>
<li>
<p>
Symlinks for paths
</p>
</li>
<li>
<p>
Additional mappings for artifact specifications
</p>
</li>
</ul></div>
<div class="paragraph"><p>WORK IN PROGRESS
mizdebsk, 31 Oct 2013</p></div>
</div>
<div class="sect3">
<h4 id="compat_packages">3.2.4. Compatibility versions</h4>
<div class="paragraph"><p>Handling of compatibility packages, versioned jars etc.</p></div>
<div class="paragraph"><p>WORK IN PROGRESS
mizdebsk, 31 Oct 2013</p></div>
</div>
</div>
<div class="sect2">
<h3 id="dependency_handling">3.3. Dependency Handling</h3>
<div class="paragraph"><p>WORK IN PROGRESS
mizdebsk, 25 Oct 2013</p></div>
<div class="paragraph"><p>Describe RPM Provides and Requires, their interactions especially with relation
to JAR file identification, explain mvn(gId:aId&#8230;) strings.</p></div>
</div>
<div class="sect2">
<h3 id="_javadoc_packages">3.4. Javadoc packages</h3>
<div class="paragraph"><p>Javadoc subpackages in Fedora provide automatically generated API
documentation for Java libraries and applications. <a href="#openjdk">Java Development Kit</a> comes with tool called <span class="monospaced">javadoc</span>. This tool can be
used for generating the documentation from specially formated comments
in Java source files.  Output of this tool, together with license files,
usually represents only content of javadoc subpackages. Note <span class="monospaced">javadoc</span>
invocation is typically handled by build system and package maintainer
doesn&#8217;t need to deal with it directly.</p></div>
<div class="paragraph"><p>Javadoc subpackage shouldn&#8217;t depend on its base package and vice versa.
The rationale behind this rule is that documentation can usually be used
independently from application/library and therefore base package
doesn&#8217;t need to be always installed. Users are given an option to
install application and documentation separately.</p></div>
<div class="admonitionblock">
<table><tr>
<td class="icon">
<img src="./images/icons/tip.png" alt="Tip">
</td>
<td class="content">
<div class="paragraph"><p>You can learn more about <span class="monospaced">javadoc</span> from
<a href="http://www.oracle.com/technetwork/java/javase/documentation/index-137868.html">official
documentation</a>.</p></div>
</td>
</tr></table>
</div>
</div>
<div class="sect2">
<h3 id="_core_java_packages">3.5. Core Java packages</h3>
<div class="paragraph"><p>WORK IN PROGRESS
mizdebsk, 25 Oct 2013</p></div>
<div class="sect3">
<h4 id="_jvm">3.5.1. JVM</h4>
<div class="paragraph"><p>Fedora allows multiple Java Virtual Machines (JVMs) to be packaged
independently.  Java packages should not directly depend on any
particulat JVM, but instead require one of three virtual JVM packages
depending of what Java funtionality is required.</p></div>
<div class="dlist"><dl>
<dt class="hdlist1">
<strong><span class="monospaced">java-headless</span></strong>
</dt>
<dd>
<p>
    This package provides a working Java Runtime Environment (JRE)
    with some functionality disabled.  Graphics and audio support may
    be unavailable in this case.  <span class="monospaced">java-headless</span> provides
    functionality that is enough for most of packages and avoids
    pulling in a number of graphics and audio libraries as
    dependencies.  Requirement on <span class="monospaced">java-headless</span> is appropriate for
    most of Java packages.
</p>
</dd>
<dt class="hdlist1">
<strong><span class="monospaced">java</span></strong>
</dt>
<dd>
<p>
    Includes the same base functionality as <span class="monospaced">java-headless</span>, but also
    implements audio and graphics subsystems.  Packages should require
    <span class="monospaced">java</span> if they need some functionality from these subsystems, for
    example creating GUI using AWT library.
</p>
</dd>
<dt class="hdlist1">
<strong><span class="monospaced">java-devel</span></strong>
</dt>
<dd>
<p>
    Provides full Java Development Kit (JDK).  In most cases only
    packages related to Java development should have runtime
    dependencies on <span class="monospaced">java-devel</span>.  Runtime packages should require
    <span class="monospaced">java-headless</span> or <span class="monospaced">java</span>.  Some packages not strictly related to
    java development need access to libraries included with JDK, but
    not with JRE (for example <span class="monospaced">tools.jar</span>).  That&#8217;s one of few cases
    where requiring java-devel may be necessary.
</p>
</dd>
</dl></div>
<div class="paragraph"><p>Packages that require minimal Java standard version can add versioned
dependencies on one of virtual packages providing Java environment.
For example if packages depending on functionality of JDK 8 can
require <span class="monospaced">java-headless &gt;= 1:1.8.0</span>.</p></div>
<div class="admonitionblock">
<table><tr>
<td class="icon">
<img src="./images/icons/note.png" alt="Note">
</td>
<td class="content">
<div class="title">Epoch in versions of JVM packages</div>
<div class="paragraph"><p>For compatibility with JPackage project packages providing Java 1.6.0
or later use epoch equal to <span class="monospaced">1</span>.  This was necessary because package
<span class="monospaced">java-1.5.0-ibm</span> from JPackage project had epoch <span class="monospaced">1</span> for some reason,
so packages providing other implementations of JVM also had to use
non-zero epoch in order to keep version ordering correct.</p></div>
</td>
</tr></table>
</div>
</div>
<div class="sect3">
<h4 id="_java_packages_tools">3.5.2. Java Packages Tools</h4>
<div class="paragraph"><p>Java Packages Tools are packaged as severas binary RPM packages</p></div>
<div class="dlist"><dl>
<dt class="hdlist1">
<strong><span class="monospaced">maven-local</span></strong>
</dt>
<dd>
<p>
    This package provides a complete environment which is required to
    build Java packages using Apache Maven build system.  This
    includes a default system version of Java Development Kit (JDK),
    Maven, a number of Maven plugins commonly used to build packages,
    various macros and utlilty tools.  <span class="monospaced">maven-local</span> is usually
    declared as build dependency of Maven packages.
</p>
</dd>
<dt class="hdlist1">
<strong><span class="monospaced">ivy-local</span></strong>
</dt>
<dd>
<p>
    Analogously to <span class="monospaced">maven-local</span>, this package provides an environment
    required to build Java packages using Apache Ivy as dependency
    manager.
</p>
</dd>
<dt class="hdlist1">
<strong><span class="monospaced">javapackages-local</span></strong>
</dt>
<dd>
<p>
    Package providing a basic environment necessary to geterate and
    install metadata for system artifact repository.
</p>
</dd>
<dt class="hdlist1">
<strong><span class="monospaced">javapackages-tools</span></strong>
</dt>
<dd>
<p>
    Package owning basic Java directories and providing runtime
    support for Java packages.  The great majority of Java packages
    depend on <span class="monospaced">javapackages-tools</span>.
</p>
</dd>
</dl></div>
<div class="paragraph"><p>TODO</p></div>
<div class="ulist"><ul>
<li>
<p>
Ant
</p>
<div class="ulist"><ul>
<li>
<p>
extra tasks and /etc/ant.d
</p>
</li>
</ul></div>
</li>
<li>
<p>
Maven
</p>
<div class="ulist"><ul>
<li>
<p>
XMvn
</p>
</li>
</ul></div>
</li>
</ul></div>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_packaging_best_practices">4. Packaging Best Practices</h2>
<div class="sectionbody">
<div class="paragraph"><p>Packaging Java has certain specifics that will be covered in this section which
will cover basic packaging principles</p></div>
<div class="ulist"><ul>
<li>
<p>
No bundling
</p>
</li>
<li>
<p>
Working with upstreams
</p>
</li>
<li>
<p>
Commenting workarounds
</p>
</li>
<li>
<p>
Single library version
</p>
</li>
<li>
<p>
Links to other appropriate documents
</p>
</li>
<li>
<p>
&#8230;
</p>
</li>
</ul></div>
</div>
</div>
<div class="sect1">
<h2 id="_generic_java_builds">5. Generic Java Builds</h2>
<div class="sectionbody">
<div class="paragraph"><p>Handling of basic build steps in Java
* javac
* usage of build-claspath, build-jar-repository to prepare for build
* &#8230;</p></div>
<div class="sect2">
<h3 id="_add_maven_depmap_macro">5.1. add_maven_depmap macro</h3>
<div class="paragraph"><p>Maven identifies JAR files by a set of strings: groupId, artifactId and version
(mostly). To let XMvn know what groupId:artifactId corresponds to which
POM or JAR file, we may use the <span class="monospaced">%add_maven_depmap</span> macro. However, if package
is build in standard way (i.e.: <span class="monospaced">%mvn_build</span> and <span class="monospaced">%mvn_install</span>), then calling
<span class="monospaced">%add_maven_depmap</span> is neither needed nor recommended.  This macro is usually
useful only for packages that use other build tool than Maven (e.g.: ant,
gradle).</p></div>
<div class="paragraph"><p>For the macro to work properly, all JAR files must be copied into <span class="monospaced">%{_javadir}</span>
and all POM files must be copied into <span class="monospaced">%{_mavenpomdir}</span>.</p></div>
<div class="paragraph"><p>In simplest form (a POM without a JAR file), <span class="monospaced">%add_maven_depmap</span> looks like
this:</p></div>
<div class="listingblock">
<div class="title">Parent POM</div>
<div class="content"></div></div>
<div class="paragraph"><p>This will read the POM file in question and provide a mapping between the
groupId and artifactId inside the POM file and the POM file placed into
<span class="monospaced">%{_mavenpomdir}</span>.</p></div>
<div class="paragraph"><p>For a POM that maps directly to a JAR file, the following is the correct form:</p></div>
<div class="listingblock">
<div class="title">Standard invocation</div>
<div class="content"></div></div>
<div class="paragraph"><p>In addition to creating the POM mapping, this will also ensure that the correct
JAR is associated with the groupId and artifactId from the POM.</p></div>
<div class="paragraph"><p>Even if there is no POM file from some reason, it is still possilbe to generate
mapping between Maven artifact and corresponding JAR file:</p></div>
<div class="listingblock">
<div class="content"></div></div>
<div class="listingblock">
<div class="title">Providing additional artifact mappings</div>
<div class="content"></div></div>
<div class="paragraph"><p>This form also adds additional mappings for given POM/JAR file. For example, if
the POM file indicates that it contains groupId commons-lang, artifactId
commons-lang, this form ensures that we also add a mapping between groupId
org.apache.commons and the installed POM/JAR files. This is necessary in cases
where the groupId or artifactId may have changed, and other packages might
require different IDs than those reflected in the installed POM.</p></div>
<div class="listingblock">
<div class="title">Multiple subpackages</div>
<div class="content"></div></div>
<div class="paragraph"><p>This form stores metadata information in file with suffix "XXX".  This
is useful for packages with multiple subpackages where each has its own
JAR files.</p></div>
<div class="listingblock">
<div class="title">Multiple artifacts in a subdirectory</div>
<div class="content"></div></div>
<div class="paragraph"><p>This form should be used when a package consists of multiple JAR files that are
installed into a subdirectory of <span class="monospaced">%{_javadir}</span>. Note that in this case, the POM
file name includes the optional subdirectory field.</p></div>
</div>
<div class="sect2">
<h3 id="_generating_application_shell_scripts">5.2. Generating Application Shell Scripts</h3>
<div class="paragraph"><p>As mentioned in section about <a href="#XFor_Packagers">Java packaging basics</a>, all
Java applications need wrapper shell scripts to setup the environment before
running JVM and associated Java code.</p></div>
<div class="paragraph"><p>The jpackage-utils package contains a convenience <span class="monospaced">%jpackage_script</span> macro that
can be used to create scripts that work for the majority of packages.  See its
definition and documentation in <span class="monospaced">/etc/rpm/macros.jpackage</span>.  One thing to pay
attention to is the 6th argument to it - whether to prefer a JRE over a full SDK
when looking up a JVM to invoke - most packages that don&#8217;t require the full Java
SDK will want to set that to <span class="monospaced">true</span> to avoid unexpected results when looking up
a JVM when some of the installed JRE&#8217;s don&#8217;t have the corresponding SDK (*-devel
package) installed.</p></div>
<div class="listingblock">
<div class="content"></div></div>
<div class="paragraph"><p>The previous example installs the "msv" script (5th argument) with main class
being msv.textui.Driver (1st argument). No optional flags (2nd argument) or
options (3rd argument) are used. This script will add several libraries to
classpath before executing main class (4th argument, JAR files separated with
":"). <span class="monospaced">build-classpath</span> is run on every part of 4th argument to create full
classpaths.</p></div>
</div>
<div class="sect2">
<h3 id="_replacing_jars_with_symlinks_using_xmvn_subst">5.3. Replacing JARs with symlinks using xmvn-subst</h3>
<div class="paragraph"><p>Sometimes it may be needed to replace all JAR files in current directory with
symlinks to the system JARs located in <span class="monospaced">%{_javadir}</span>. This task can be achieved
using tool called <span class="monospaced">xmvn-subst</span>.</p></div>
<div class="listingblock">
<div class="content"></div></div>
<div class="paragraph"><p>The example above shows how easy the symlinking can be. However, there are some
limitations. Original JAR files need to carry metadata which tell xmvn-subst
for what artifact given file should be substituted. Otherwise <span class="monospaced">xmvn-subst</span> won&#8217;t
be able to identify the Maven artifact from JAR file.</p></div>
<div class="admonitionblock">
<table><tr>
<td class="icon">
<img src="./images/icons/tip.png" alt="Tip">
</td>
<td class="content">
<div class="paragraph"><p>See <span class="monospaced">xmvn-subst -h</span> for all available options.</p></div>
</td>
</tr></table>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="ant">6. Ant</h2>
<div class="sectionbody">
<div class="quoteblock">
<div class="content">
<div class="paragraph"><p>Apache Ant is a Java library and command-line tool whose mission is to drive
processes described in build files as targets and extension points dependent
upon each other.</p></div>
</div>
<div class="attribution">
<em>http://ant.apache.org/</em>
</div></div>
<div class="paragraph"><p>Apache Ant is probably second most used Java build tool right after Apache
Maven. The main difference between these two tools is that Ant is procedural and
Maven is declarative. When using Ant, it is neccessary to exactly describe the
processes which lead to the result. It means that one needs to specify where the
source files are, what needs to be done and when it needs to be done. On the
other hand, Maven relies on conventions and doesn&#8217;t require specifying most
of the process unless you need to override the defaults.</p></div>
<div class="paragraph"><p>If upstream ships a Maven POM file, it must be installed even if you
don&#8217;t build with Maven. If not you should try to search Maven Central
Repository for it, ship it as another source and install it.</p></div>
<div class="listingblock">
<div class="title">Common spec file</div>
<div class="content"></div></div>
<div class="paragraph"><p>Details:</p></div>
<div class="ulist"><ul>
<li>
<p>
<span class="monospaced">%build</span> section uses <span class="monospaced">ant</span> command to build the project and run the
      tests. The used target(s) may vary depending on the <span class="monospaced">build.xml</span>
      file. You can use <span class="monospaced">ant -p</span> command to list the project info or
      manually look for <span class="monospaced">&lt;target&gt;</span> nodes in the <span class="monospaced">build.xml</span> file
</p>
</li>
<li>
<p>
<span class="monospaced">%mvn_artifact</span> macro is used to request installation of an
      artifact that was not built using Maven. It expects a POM file and
      a JAR file. For POM only artifacts, the JAR part is omitted.<br>
      See <a href="#mvn_artifact">Installing additional artifacts</a> for more
      information
</p>
</li>
<li>
<p>
<span class="monospaced">%mvn_install</span> performs the actual installation. Optional <span class="monospaced">-J</span>
      parameter requests installation of generated Javadoc from given
      directory
</p>
</li>
<li>
<p>
This method of artifact installation allows using other XMvn
      macros such as <span class="monospaced">%mvn_alias</span> or <span class="monospaced">%mvn_package</span>
</p>
</li>
<li>
<p>
<span class="monospaced">%mvn_install</span> generates <span class="monospaced">.mfiles</span> file which should be used to
      populate <span class="monospaced">%files</span> section with <span class="monospaced">-f</span> switch. For each subpackage
      there would be separate generated file named
      <span class="monospaced">.mfiles-subpackage-name</span>
</p>
</li>
<li>
<p>
All packages are required to own directories which they create
      (and which are not owned by other packages). JAR files are by
      default installed into subdirectory of <span class="monospaced">%{_javadir}</span>. To override
      this behavior, use <span class="monospaced">%mvn_file</span>
</p>
</li>
</ul></div>
<div class="sect2">
<h3 id="_apache_ivy">6.1. Apache Ivy</h3>
<div class="paragraph"><p>Apache Ivy provides an automatic dependency management for Ant managed
builds. It uses Maven repositories for retrieving artifacts and supports
many declarative features of Maven such as handling transitive
dependencies.</p></div>
<div class="paragraph"><p>XMvn supports local resolution of Ivy artifacts, their installation
and requires generation.</p></div>
<div class="listingblock">
<div class="title">Spec file</div>
<div class="content"></div></div>
<div class="paragraph"><p>Details:</p></div>
<div class="ulist"><ul>
<li>
<p>
<span class="monospaced">-Divy.mode=local</span> tells Ivy to use XMvn local artifact
      resolution instead of downloading from the Internet
</p>
</li>
<li>
<p>
If there is an <span class="monospaced">ivy-settings.xml</span> or similar file, which specifies
      remote repositories, it needs to be disabled, otherwise it would
      override local resolution.
</p>
</li>
<li>
<p>
<span class="monospaced">%mvn_artifact</span> supports installing artifacts described by Ivy
      configuration files
</p>
</li>
<li>
<p>
<span class="monospaced">%mvn_install</span> performs the actual installation. Optional <span class="monospaced">-J</span>
      parameter requests installation of generated Javadoc from given
      directory
</p>
</li>
</ul></div>
<div class="paragraph"><div class="title">Ivy files manipulation</div><p>A subset of macros used to modify Maven POMs also work with <span class="monospaced">ivy.xml</span>
files allowing the maintainer to add/remove/change dependencies without
the need of making patches and rebasing them with each change.
You can use dependency handling macros <span class="monospaced">%pom_add_dep</span>,
<span class="monospaced">%pom_remove_dep</span>, <span class="monospaced">%pom_change_dep</span> and generic <span class="monospaced">%pom_xpath_*</span> macros.
For more details, see corresponding manpages.</p></div>
<div class="listingblock">
<div class="content"></div></div>
<div class="paragraph"><div class="title">Using the <span class="monospaced">ivy:publish</span> task</div><p>Ivy supports publishing built artifact with <span class="monospaced">ivy:publish</span> task. If your
<span class="monospaced">build.xml</span> file already contains a task that calls <span class="monospaced">ivy:publish</span>, you
can set the resolver attribute of the <span class="monospaced">ivy:publish</span> element to <span class="monospaced">xmvn</span>.
This can be done with simple <span class="monospaced">%pom_xpath_set</span> call.  Then when the task
is run, XMvn can pick the published artifacts and install them during
the run of <span class="monospaced">%mvn_install</span> without needing you to manually specify them
with
<span class="monospaced">%mvn_artifact</span>.</p></div>
<div class="listingblock">
<div class="title">Spec file using the <span class="monospaced">ivy:publish</span> task</div>
<div class="content"></div></div>
<div class="paragraph"><p>Details:</p></div>
<div class="ulist"><ul>
<li>
<p>
The publish target may be named differently. Search the <span class="monospaced">build.xml</span>
      for occurences of <span class="monospaced">ivy:publish</span>.
</p>
</li>
<li>
<p>
<span class="monospaced">%mvn_install</span> will install all the published artifacts.
</p>
</li>
</ul></div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="maven">7. Maven</h2>
<div class="sectionbody">
<div class="quoteblock">
<div class="content">
<div class="paragraph"><p>Apache Maven is a software project management and comprehension tool. Based on
the concept of a project object model (POM), Maven can manage a project&#8217;s build,
reporting and documentation from a central piece of information.</p></div>
</div>
<div class="attribution">
<em>http://maven.apache.org</em>
</div></div>
<div class="paragraph"><p>Maven is by far the most consistent Java build system, allowing large amount of
automation. In most common situations only following steps are necessary:</p></div>
<div class="olist arabic"><ol class="arabic">
<li>
<p>
In <span class="monospaced">%build</span> section of the spec file use <span class="monospaced">%mvn_build</span> macro
</p>
</li>
<li>
<p>
In <span class="monospaced">%install</span> section, use <span class="monospaced">%mvn_install</span> macro
</p>
</li>
<li>
<p>
Use generated file <span class="monospaced">.mfiles</span> lists to populate <span class="monospaced">%files</span> section with <span class="monospaced">-f</span> switch
</p>
</li>
</ol></div>
<div class="listingblock">
<div class="title">Common spec file sections</div>
<div class="content"></div></div>
<div class="paragraph"><p>The macros <span class="monospaced">%mvn_build</span> and <span class="monospaced">%mvn_install</span> automatically handle building of the
JAR files and their subsequent installation to the correct directory. The
corresponding POM and metadata files are also installed.</p></div>
<div class="sect2">
<h3 id="packaging_maven_project">7.1. Packaging Maven project</h3>
<div class="paragraph"><p>This step by step guide will show you how to package Maven project. Let&#8217;s start with
probably simplest spec file possible.</p></div>
<div class="listingblock">
<div class="content"></div></div>
<div class="paragraph"><p>The spec file above is a real world example how it may look like for simple Maven
project. Both <span class="monospaced">%build</span> and <span class="monospaced">%install</span> sections consist only of one line.</p></div>
<div class="paragraph"><p>Another interesting lines:</p></div>
<div class="listingblock">
<div class="content"></div></div>
<div class="paragraph"><p>All Maven projects need to have BuildRequires on <span class="monospaced">maven-local</span>. They also need
to have Requires and BuildRequires on <span class="monospaced">jpackages-utils</span>, but build system adds
these automatically. Package maintainer doesn&#8217;t need to list them explicitly.</p></div>
<div class="listingblock">
<div class="content"></div></div>
<div class="paragraph"><p>By default, resulting JAR files will be installed in <span class="monospaced">%{_javadir}/%{name}</span>,
therefore package needs to own this directory.</p></div>
<div class="paragraph"><p>The build could fail from many reasons, but one probably most common is
build failure due to <a href="#error_missing_dependency">missing dependencies</a></p></div>
<div class="paragraph"><p>We can try to remove these missing dependencies from pom.xml and make Maven
stop complaining about them. However, these removed dependencies may be crucial
for building of the project and therefore it may be needed to package them
later.  Let&#8217;s remove the dependencies from <span class="monospaced">pom.xml</span>.</p></div>
<div class="listingblock">
<div class="title">Remove dependencies from pom.xml</div>
<div class="content"></div></div>
<div class="paragraph"><p>Package maintainer can use a wide variety of "<span class="monospaced">pom_</span>" macros for modifying
<span class="monospaced">pom.xml</span> files. See <a href="#helper_macros">Macros for POM modification</a> section for more information.</p></div>
<div class="paragraph"><p>Now try to build the project again. The build will fail with
<a href="#error_compilation_failure">compilation failure</a>.</p></div>
<div class="paragraph"><p>Oops, another problem. This time Maven thought it had all the necessary dependencies, but Java
compiler thinks otherwise.</p></div>
<div class="paragraph"><p>Now it&#8217;s possible to either patch the source code not to depend on
missing libraries or to package them. Second approach is usually correct. It&#8217;s not necessary to package every
dependency right away. Maintainer could package compile time dependencies first and keep the
rest for later (test dependencies, &#8230;). But Maven needs to know that it shouldn&#8217;t try to run tests now. This can be achieved by passing <span class="monospaced">-f</span> option to <span class="monospaced">%mvn_build</span> macro.  Maven
will stop complaining about missing test scoped dependencies from now on.</p></div>
<div class="admonitionblock">
<table><tr>
<td class="icon">
<img src="./images/icons/note.png" alt="Note">
</td>
<td class="content">
<div class="paragraph"><p>It is always recommended to run all available test suites during build. It greatly improves quality of the package.</p></div>
</td>
</tr></table>
</div>
<div class="paragraph"><p>We already have package which provides <span class="monospaced">commons-io:commons-io</span> artifact, let&#8217;s add it to the <span class="monospaced">BuildRequires</span>. Also disable tests for now.</p></div>
<div class="listingblock">
<div class="content"></div></div>
<div class="admonitionblock">
<table><tr>
<td class="icon">
<img src="./images/icons/tip.png" alt="Tip">
</td>
<td class="content">
<div class="paragraph"><p>One can easily search for package which provides desired artifact. Try
<span class="monospaced">repoquery -f 'mvn(commons-io:commons-io)'</span>, or see how to
<a href="#querying_repositories">query repositories</a>.</p></div>
</td>
</tr></table>
</div>
<div class="paragraph"><p>Now try to build the project one more time. The build should succeed now. Congrats, you managed to create an RPM from Maven project!</p></div>
<div class="paragraph"><p>There is plenty of other things maintainer may want to do. For example, he may want to provide symbolic links to the JAR file
in <span class="monospaced">%{_javadir}</span>.</p></div>
<div class="paragraph"><p>This can be easily achieved with <span class="monospaced">%mvn_file</span> macro:</p></div>
<div class="listingblock">
<div class="content"></div></div>
<div class="paragraph"><p>See <a href="#mvn_file">Alternative JAR File Names</a> section for more information.</p></div>
<div class="paragraph"><p>Another quite common thing to do is adding aliases to Maven artifact. Try to run <span class="monospaced">rpm
-qp --provides</span> on your locally built RPM package:</p></div>
<div class="listingblock">
<div class="content"></div></div>
<div class="paragraph"><p>The output above tells us that the RPM package provides Maven artifact
"com.example:simplemaven:1.0". Upstream may change the groupId:artifactId with
any new release. And it happens. For example org.apache.commons:commons-io
changed to commons-io:commons-io some time ago.  It&#8217;s not a big deal for package
itself, but it is a huge problem for other packages that depends on that
particular package. Some packages may still have dependencies on old
groupId:artifactId, which is suddenly unavailable. Luckily, there is an easy way
how to solve the problems like these. Package maintainer can add aliases to actually provided
Maven artifact.</p></div>
<div class="listingblock">
<div class="title">Add alias to Maven artifact</div>
<div class="content"></div></div>
<div class="paragraph"><p>See <a href="#mvn_alias">Additional Mappings</a> for more information on <span class="monospaced">%mvn_alias</span>.</p></div>
<div class="paragraph"><p>Rebuild the pacakge and check <span class="monospaced">rpm -qp --provides</span> output again:</p></div>
<div class="listingblock">
<div class="content"></div></div>
<div class="paragraph"><p>Now it doesn&#8217;t matter if some other package depends on either of these listed
artifact. Both dependencies will always be satisfied with your package.</p></div>
<div class="admonitionblock">
<table><tr>
<td class="icon">
<img src="./images/icons/note.png" alt="Note">
</td>
<td class="content">One could try to fix dependencies in all the dependent packages
instead of adding an alias to single package. It&#8217;s almost always wrong thing to
do.</td>
</tr></table>
</div>
</div>
<div class="sect2">
<h3 id="mvn_macros">7.2. Macros for Maven build configuration</h3>
<div class="paragraph"><p>Maven builds can be configured to produce alternative layout, include additional
aliases in package metadata or create separate subpackages for certain
artifacts.</p></div>
<div class="sect3">
<h4 id="mvn_artifact">7.2.1. Installing additional artifacts</h4>
<div class="paragraph"><p>It is possible to explicitly request an installation of any Maven artifact
(JAR/POM file).  Macro <span class="monospaced">%mvn_install</span> only knows about Maven artifacts that were
created during execution of <span class="monospaced">%mvn_build</span>. Normally, any other artifacts which
were built by some other method would need to be installed manually.
<span class="monospaced">%mvn_build</span> macro doesn&#8217;t even need to be used at all. Luckily, all artifacts
created outside of <span class="monospaced">%mvn_build</span> can be marked for installation with
<span class="monospaced">%mvn_artifact</span> macro. This macro creates configuration for <span class="monospaced">%mvn_install</span>.</p></div>
<div class="listingblock">
<div class="title">Requesting installation of Maven artifact</div>
<div class="content"></div></div>
</div>
<div class="sect3">
<h4 id="mvn_alias">7.2.2. Additional Mappings</h4>
<div class="paragraph"><p>The macro <span class="monospaced">%mvn_alias</span> can be used to add additional mappings for given POM/JAR
file. For example, if the POM file indicates that it contains groupId
commons-lang, artifactId commons-lang, this macro ensures that we also add a
mapping between groupId org.apache.commons and the installed JAR/POM files. This
is necessary in cases where the groupId or artifactId may have changed, and
other packages might require different IDs than those reflected in the installed
POM.</p></div>
<div class="listingblock">
<div class="title">Adding more mappings for JAR/POM files example</div>
<div class="content"></div></div>
</div>
<div class="sect3">
<h4 id="mvn_file">7.2.3. Alternative JAR File Names</h4>
<div class="paragraph"><p>In some cases, it may be important to be able to provide symbolic links to actual JAR
files. This can be achieved with <span class="monospaced">%mvn_file</span> macro. This macro allows packager
to specify names of the JAR files, their location in <span class="monospaced">%{_javadir}</span> directory and
also can create symbolic links to the JAR files. These links can be possibly
located outside of the <span class="monospaced">%{_javadir}</span> directory.</p></div>
<div class="listingblock">
<div class="title">Adding file symlinks to compatibility</div>
<div class="content"></div></div>
<div class="paragraph"><p>This means that JAR file for artifact with ID "guice" (and any groupId) will be
installed in <span class="monospaced">%{_javadir}/google/guice.jar</span> and there also will be a symbolic links to
this JAR file located in <span class="monospaced">%{_javadir}/guice.jar</span>. Note the macro will add ".jar"
extensions automatically.</p></div>
</div>
<div class="sect3">
<h4 id="mvn_singleton">7.2.4. Single Artifact Per Package</h4>
<div class="paragraph"><p>If the project consists of multiple artifacts, it is recommended to install each
artifact to the separate subpackage. The macro <span class="monospaced">%mvn_build -s</span> will generate
separate <span class="monospaced">.mfiles</span> file for every artifact in the project. This file contains
list of files related to specific artifact (typically JAR file, POM file and
metadata). It can be later used in <span class="monospaced">%files</span> section of the spec file.</p></div>
<div class="listingblock">
<div class="title">Creating one subpackage for each generated artifact</div>
<div class="content"></div></div>
</div>
<div class="sect3">
<h4 id="mvn_package">7.2.5. Assignment of the Maven Artifacts to the Subpackages</h4>
<div class="paragraph"><p>The macro <span class="monospaced">%mvn_package</span> allows maintainer to specify in which exact package the
selected artifact will end up. It is something between singleton packaging, when
each artifact has its own subpackage and default packaging, when all artifacts
end up in the same package.</p></div>
<div class="listingblock">
<div class="title">Assigning multiple artifacts to single subpackage</div>
<div class="content"></div></div>
<div class="paragraph"><p>In above example, the artifacts <span class="monospaced">plexus-compiler-jikes</span>,
<span class="monospaced">plexus-compiler-eclipse</span>, <span class="monospaced">plexus-compiler-csharp</span> will end up in package named
<span class="monospaced">plexus-compiler-extras</span>. If there are some other artifacts beside these three
mentioned (e.g. some parent POMs), then these will all end up in package named
<span class="monospaced">%{name}</span>.</p></div>
<div class="admonitionblock">
<table><tr>
<td class="icon">
<img src="./images/icons/tip.png" alt="Tip">
</td>
<td class="content">
<div class="paragraph"><p><span class="monospaced">%mvn_package</span> macro supports wildcards and brace expansions, so whole <span class="monospaced">%prep</span> section from previous example can be replaced with single line:
<span class="monospaced">%mvn_package ":plexus-compiler-{jikes,eclipse,csharp}" plexus-compiler-extras</span></p></div>
</td>
</tr></table>
</div>
<div class="paragraph"><p>It is possible to assign artifacts into a package called <span class="monospaced">__noinstall</span>. This package
name has a special meaning. And as you can guess, artifacts assigned into this
package won&#8217;t be installed anywhere and the package itself won&#8217;t be created.</p></div>
<div class="listingblock">
<div class="title">Skipping installation of an artifact</div>
<div class="content"></div></div>
</div>
<div class="sect3">
<h4 id="mvn_config">7.2.6. Modifying XMvn configuration from within spec file</h4>
<div class="paragraph"><p>Some packages might need to modify XMvn&#8217;s configuration in order to build
successfully or from other reasons. This can be achieved with <span class="monospaced">mvn_config</span>
macro. For example, some old package can use <span class="monospaced">enum</span> as an identifier, but it is
also keyword since Java 1.5. Such package will probably fail to build on current
systems. This problem can be easily solved by passing <span class="monospaced">-source 1.4</span> to the
compiler, so one could add following line to the spec file:</p></div>
<div class="listingblock">
<div class="title">Overriding default XMvn configuration</div>
<div class="content"></div></div>
<div class="paragraph"><p>XMvn&#8217;s configuration is quite complex, but well documented at project&#8217;s
<a href="http://mizdebsk.fedorapeople.org/xmvn/site/">official website</a>. The website
should always be used as a primary source of information about XMvn
configuration.</p></div>
<div class="admonitionblock">
<table><tr>
<td class="icon">
<img src="./images/icons/tip.png" alt="Tip">
</td>
<td class="content">
<div class="paragraph"><p>Read about XMvn&#8217;s configuration
<a href="http://mizdebsk.fedorapeople.org/xmvn/site/configuration.html">basics</a> and see
full <a href="http://mizdebsk.fedorapeople.org/xmvn/site/config.html">configuration reference</a>.</p></div>
</td>
</tr></table>
</div>
<div class="admonitionblock">
<table><tr>
<td class="icon">
<img src="./images/icons/tip.png" alt="Tip">
</td>
<td class="content">
<div class="paragraph"><p>All <span class="monospaced">%mvn_</span> macros have their own manual page which contains details on how to
use them. All possible options should be documented there. These manual pages
should be considered most up to date documentation right after source code. Try
for example <span class="monospaced">man mvn_file</span>.</p></div>
</td>
</tr></table>
</div>
</div>
</div>
<div class="sect2">
<h3 id="helper_macros">7.3. Macros for POM modification</h3>
<div class="paragraph"><p>Sometimes Maven <span class="monospaced">pom.xml</span> files need to be patched before they are used
to build packages. One could use traditional patches to maintain
changes, but package maintainers should use <span class="monospaced">%pom_*</span> macros developed
specially to ease this task.</p></div>
<div class="paragraph"><p>These macros are designed to be called from <span class="monospaced">%prep</span> section of spec
files. They are documented in <span class="monospaced">/usr/lib/rpm/macros.d/macros.fjava</span> configuration
file, which is also
<a href="https://git.fedorahosted.org/cgit/javapackages.git/plain/macros.d/macros.fjava">available
online</a> and all the macros also have their own manual page. See the
manual pages for technical details how to use them.</p></div>
<div class="admonitionblock">
<table><tr>
<td class="icon">
<img src="./images/icons/note.png" alt="Note">
</td>
<td class="content">
<div class="title">Handling XML namespaces</div>
<div class="paragraph"><p>POM files use a specific namespace - <a href="http://maven.apache.org/POM/4.0.0">http://maven.apache.org/POM/4.0.0</a>.
The easiest way to respect this namespace in XPath expressions is
prefixing all node names with <span class="monospaced">pom:</span>. For example,
<span class="monospaced">pom:environment/pom:os</span> will work because it selects nodes from <span class="monospaced">pom</span>
namespace, but <span class="monospaced">environment/os</span> won&#8217;t find anything because it looks for
nodes that don&#8217;t belong to any XML namespace. It is needed even if the
original POM file didn&#8217;t contain proper POM namespace, since it will be
added automatically.</p></div>
</td>
</tr></table>
</div>
<div class="paragraph"><p>Using <span class="monospaced">%pom_*</span> macros not only increases readability of the spec file,
but also improves maintainability of the package as there are no patches
that would need to be rebased with each upstream release. Below are some
examples added for convenience.</p></div>
<div class="sect3">
<h4 id="pom_remove_dep">7.3.1. Adding/removing dependencies</h4>
<div class="paragraph"><p>Often dependencies specified in Maven <span class="monospaced">pom.xml</span> files need to be removed
because of different reasons. <span class="monospaced">%pom_remove_dep</span> macro can be used to
ease this task:</p></div>
<div class="listingblock">
<div class="title">Removing dependencies from pom.xml files</div>
<div class="content"></div></div>
<div class="paragraph"><div class="title">Recursive mode</div><p>POM macros which remove elements can work in recursive mode, allowing
the maintainer to remove given dependency/plugin from all the poms
without the need to enumerate all POMs manually. It recursively
traverses all enabled submodules of given <span class="monospaced">pom.xml</span> by looking at
<span class="monospaced">&lt;module&gt;</span> nodes. It is activated by <span class="monospaced">-r</span> switch.</p></div>
<div class="listingblock">
<div class="content"></div></div>
<div class="paragraph"><div class="title">Adding dependencies</div><p>Dependencies can also be added to <span class="monospaced">pom.xml</span> with <span class="monospaced">%pom_add_dep</span> macro.
Usage is very similar to <span class="monospaced">%pom_remove_dep</span>, see <span class="monospaced">"man pom_add_dep"</span> for
more information.</p></div>
<div class="paragraph"><div class="title">Changing dependencies</div><p>Sometimes the artifact coordinates used in upstream <span class="monospaced">pom.xml</span> don&#8217;t
correspond to ones used in Fedora and you need to modify them.
<span class="monospaced">%pom_change_dep</span> macro will modify all dependencies matching the first
argument to artifact coordinates specified by the second argument. Note
this macro also works in recursive mode.</p></div>
<div class="listingblock">
<div class="content"></div></div>
</div>
<div class="sect3">
<h4 id="pom_remove_plugin">7.3.2. Adding/removing plugins</h4>
<div class="paragraph"><p><span class="monospaced">%pom_remove_plugin</span> macro works exactly as <span class="monospaced">%pom_remove_dep</span>, except it removes
Maven plugin invocations. Some examples:</p></div>
<div class="listingblock">
<div class="title">Removing Maven plugins from pom.xml files</div>
<div class="content"></div></div>
<div class="paragraph"><p>Like in previous case, there is also a macro for adding plugins to
<span class="monospaced">pom.xml</span>. See <span class="monospaced">"man pom_add_plugin"</span> for more information.</p></div>
</div>
<div class="sect3">
<h4 id="pom_disable_module">7.3.3. Disabling unneeded modules</h4>
<div class="paragraph"><p>Sometimes some submodules of upstream project cannot be built for
various reasons and there is a need to disable them. This can be
achieved by using <span class="monospaced">%pom_disable_module</span>, for example:</p></div>
<div class="listingblock">
<div class="title">Disabling specific project modules</div>
<div class="content"></div></div>
</div>
<div class="sect3">
<h4 id="pom_remove_parent">7.3.4. Working with parent POM references</h4>
<div class="paragraph"><p>Macro <span class="monospaced">%pom_remove_parent</span> removes reference to a parent POM from Maven
POM files. This can be useful when parent POM is not yet packaged (e.g.
because of licensing issues) and at the same time it&#8217;s not really needed
for building of the project. There are also macros for adding parent POM
reference (<span class="monospaced">%pom_add_parent</span>) and replacing existing reference with new
one (<span class="monospaced">%pom_set_parent</span>).</p></div>
<div class="listingblock">
<div class="title">Manipulating parent POM references</div>
<div class="content"></div></div>
</div>
<div class="sect3">
<h4 id="pom_xpath_remove">7.3.5. Macros for performing generic modifications</h4>
<div class="paragraph"><p>The above macros cover the most common cases of modifying <span class="monospaced">pom.xml</span>
files, however if there is a need to apply some less-common patches
there are also three generic macros for modifying <span class="monospaced">pom.xml</span> files.
<span class="monospaced">%pom_xpath_remove</span> can be used to remove arbitrary XML nodes, described
by <a href="http://www.w3.org/TR/xpath/">XPath</a> 1.0 expressions.
<span class="monospaced">%pom_xpath_inject</span> macro is capable of injecting arbitrary
<a href="http://www.w3.org/TR/xml/">XML</a> code to any <span class="monospaced">pom.xml</span> file. And
finally, <span class="monospaced">%pom_xpath_set</span> replaces content of the arbitrary XML nodes
with specified value.  Below you can find some examples for these
macros.</p></div>
<div class="listingblock">
<div class="title">Less common pom.xml modifications</div>
<div class="content"></div></div>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_common_errors">8. Common Errors</h2>
<div class="sectionbody">
<div class="paragraph"><p>This section contains explanations and solutions/workarounds for common
errors which can be encountered during packaging.</p></div>
<div class="sect2">
<h3 id="error_missing_dependency">8.1. Missing dependency</h3>
<div class="listingblock">
<div class="content monospaced">
<pre>[ERROR] Failed to execute goal on project simplemaven: Could not resolve
dependencies for project com.example:simplemaven:jar:1.0: The following
artifacts could not be resolved: commons-io:commons-io:jar:2.4,
junit:junit:jar:4.11: Cannot access central
(http://repo.maven.apache.org/maven2) in offline mode and the artifact
commons-io:commons-io:jar:2.4 has not been downloaded from it before. -&gt; [Help
1]</pre>
</div></div>
<div class="paragraph"><p>Maven wasn&#8217;t able to build project <span class="monospaced">com.example:simplemaven</span>, because it
couldn&#8217;t find some dependencies (in this case
<span class="monospaced">commons-io:commons-io:jar:2.4</span> and <span class="monospaced">junit:junit:jar:4.11</span>)</p></div>
<div class="paragraph"><p>Package maintainer has two options here:</p></div>
<div class="ulist"><ul>
<li>
<p>
find out which packages provide given dependencies and add them to
   <span class="monospaced">BuildRequires</span> in the spec file. Use <span class="monospaced">repoquery -f
   'mvn(commons-io:commons-io)'</span> to search for package which provides
   given artifact.
</p>
</li>
<li>
<p>
remove those dependencies from <span class="monospaced">pom.xml</span> file. Maven will stop
   complaining about them and some dependencies don&#8217;t have to be
   mandatory for project to build. Maintainer can use wide variety of
   <a href="#helper_macros">macros</a> for modifying POM files. The one
   for removing dependencies is called
   <a href="#pom_remove_dep">%pom_remove_dep</a>. If removed dependency was
   actually needed, the build will later fail with compilation failure.
</p>
</li>
</ul></div>
</div>
<div class="sect2">
<h3 id="error_compilation_failure">8.2. Compilation failure</h3>
<div class="listingblock">
<div class="content monospaced">
<pre>[ERROR] Failed to execute goal
        org.apache.maven.plugins:maven-compiler-plugin:3.1:compile (default-compile)
        on project simplemaven: Compilation failure: Compilation failure:
[ERROR]
/builddir/build/BUILD/simplemaven-1.0/src/main/java/com/example/Main.java:[3,29]
package org.apache.commons.io does not exist
[ERROR]
/builddir/build/BUILD/simplemaven-1.0/src/main/java/com/example/Main.java:[8,9]
cannot find symbol
[ERROR] symbol:   class FileUtils
[ERROR] location: class com.example.Main
[ERROR] -&gt; [Help 1]</pre>
</div></div>
<div class="paragraph"><p>Java compiler couldn&#8217;t find given class on classpath or incompatible
version was present. This could be caused by following reasons:</p></div>
<div class="ulist"><ul>
<li>
<p>
<span class="monospaced">pom.xml</span> requires different version of Maven artifact than local
   repository provides
</p>
</li>
<li>
<p>
<span class="monospaced">pom.xml</span> is missing necessary dependency
</p>
</li>
</ul></div>
<div class="paragraph"><p>Different versions of same library may provide slightly different API.
This means that project doesn&#8217;t have to be buildable if different
version is provided.  If the library in local repository is older than
the one required by project, then the library could be updated. If the
project requires older version, then the project should be ported to
latest stable version of the library (this may require cooperation with
project&#8217;s upstream). If none of these is possible from some reason, it
is still possible to introduce new <span class="monospaced">compat</span> package. See
<a href="#compat_packages">compat packages</a> section for more information on this
topic.</p></div>
<div class="paragraph"><p>Sometimes <span class="monospaced">pom.xml</span> doesn&#8217;t list all the necessary dependencies, even if
it should. Dependencies can also depend on some other and typically all
these will be available to the project which is being built. The problem
is that local repository may contain different versions of these
dependencies. And even if these versions are fully compatible with the
project, they may require slightly different set of dependencies. This
could lead to build failure if <span class="monospaced">pom.xml</span> doesn&#8217;t specify all necessary
dependencies and relies on transitive dependencies. Such a missing
dependency may be considered a bug in the project. The solution is to
explicitly add missing dependency to the <span class="monospaced">pom.xml</span>. This may be easily
done by using <span class="monospaced">%pom_add_dep</span> macro. See section about
<a href="#helper_macros">macros for POM modification</a> for more information.</p></div>
</div>
<div class="sect2">
<h3 id="error_requires_unknown">8.3. Requires cannot be generated</h3>
<div class="listingblock">
<div class="content monospaced">
<pre>Following dependencies were not resolved and requires cannot be generated. Either remove the dependency from pom.xml or add proper packages to BuildRequires:
org.apache.maven.doxia:doxia-core::tests:UNKNOWN</pre>
</div></div>
<div class="paragraph"><p>Most often this error happens when one part of the package depends on an
attached artifact which is not being installed. Automatic RPM requires generator
then tries to generate requires on artifact which is not being installed. This
would most likely result in a broken RPM package so generator halts the build.</p></div>
<div class="paragraph"><p>There are usually two possible solutions for this problem:</p></div>
<div class="ulist"><ul>
<li>
<p>
Install attached artifact in question. For the above error following macro
   would install artifacts with <span class="monospaced">tests</span> classifiers into <span class="monospaced">tests</span> subpackage.
</p>
<div class="literalblock">
<div class="content monospaced">
<pre>%mvn_package :::tests: %{name}-tests</pre>
</div></div>
</li>
<li>
<p>
Remove dependency on problematic artifact. This can involve <span class="monospaced">pom.xml</span>
   modifications, disabling tests or even code changes so it is usually easier
   to install the dependency.
</p>
</li>
</ul></div>
</div>
<div class="sect2">
<h3 id="error_scope_system">8.4. Dependencies with scope "system"</h3>
<div class="listingblock">
<div class="content monospaced">
<pre>[ERROR] Failed to execute goal
org.fedoraproject.xmvn:xmvn-mojo:1.2.0:install (default-cli) on project
pom: Some reactor artifacts have dependencies with scope "system". Such
dependencies are not supported by XMvn installer. You should either
remove any dependencies with scope "system" before the build or not run
XMvn instaler. -&gt; [Help 1]</pre>
</div></div>
<div class="paragraph"><p>Some Maven artifacts try to depend on exact system paths. Most usually this
dependency is either on <span class="monospaced">com.sun:tools</span> or <span class="monospaced">sun.jdk:jconsole</span>. Dependencies with
system scope cause issues with our tooling and requires generators so they are
not supported.</p></div>
<div class="paragraph"><p>Easiest way to solve this for above two dependencies is by removing and adding
back the dependency without <span class="monospaced">&lt;scope&gt;</span> or <span class="monospaced">&lt;systemPath&gt;</span> nodes:</p></div>
<div class="literalblock">
<div class="content monospaced">
<pre>%pom_remove_dep com.sun:tools
%pom_add_dep com.sun:tools</pre>
</div></div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_integration_of_maven_and_xmvn_tools">9. Integration of Maven and XMvn Tools</h2>
<div class="sectionbody">
<div class="paragraph"><p>Describe common usage patterns of XMvn, xmvn-bisect and other tools with links
to upstream documentation where it makes sense</p></div>
<div class="paragraph"><p>TODO - write content</p></div>
</div>
</div>
<div class="sect1">
<h2 id="_migration_from_older_tools">10. Migration from older tools</h2>
<div class="sectionbody">
<div class="paragraph"><p>This section describes how to migrate packages that use older deprecated
tools to current ones.</p></div>
<div class="sect2">
<h3 id="_add_maven_depmap_macro_2">10.1. add_maven_depmap macro</h3>
<div class="paragraph"><p><span class="monospaced">%add_maven_depmap</span> macro was used to manually install Maven artifacts
that were built with Apache Ant or <span class="monospaced">mvn-rpmbuild</span>. It
is now deprecated and its invocations should be replaced with
<span class="monospaced">%mvn_artifact</span> and <span class="monospaced">%mvn_install</span>.</p></div>
<div class="paragraph"><p>Artifact files, Maven POM files and their installation directories no
longer need to be manually installed, since that is done
during run of <span class="monospaced">%mvn_install</span>. The installed files also don&#8217;t need to be
explicitly enumerated in <span class="monospaced">%files</span> section. Generated file <span class="monospaced">.mfiles</span>
should be used instead.</p></div>
<div class="paragraph"><p>Relevant parts of specfile using <span class="monospaced">%add_maven_depmap</span></p></div>
<div class="listingblock">
<div class="content"></div></div>
<div class="paragraph"><p>The same specfile migrated to <span class="monospaced">%mvn_artifact</span> and <span class="monospaced">%mvn_install</span></p></div>
<div class="listingblock">
<div class="content"></div></div>
<div class="paragraph"><div class="title">Aliases and subpackages</div><p><span class="monospaced">%add_maven_depmap</span> had <span class="monospaced">-a</span> switch to specify artifact aliases and <span class="monospaced">-f</span>
switch to support splitting artifacts across multiple subpackages. To
achieve the same things with <span class="monospaced">%mvn_*</span> macros, see <a href="#mvn_alias">Additional Mappings</a> and <a href="#mvn_package">Assignment of the Maven Artifacts to the Subpackages</a>.</p></div>
<div class="admonitionblock">
<table><tr>
<td class="icon">
<img src="./images/icons/tip.png" alt="Tip">
</td>
<td class="content">
<div class="paragraph"><p>If project consists of multiple artifacts and parent POMs are among them, call <span class="monospaced">%mvn_artifact</span> on these parent POMs first.</p></div>
</td>
</tr></table>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_appendix">11. Appendix A: Appendix</h2>
<div class="sectionbody">
<div class="paragraph"><p>Ideally include manpages for mvn_ and pom_ macros here</p></div>
</div>
</div>
<div class="sect1">
<h2 id="_references">12. References</h2>
<div class="sectionbody">
<div class="ulist bibliography"><ul>
<li>
<p>
<a id="guidelines"></a>[guidelines] <a href="https://fedoraproject.org/wiki/Packaging:Java">https://fedoraproject.org/wiki/Packaging:Java</a>
</p>
</li>
<li>
<p>
<a id="walsh-muellner"></a>[walsh-muellner] Norman Walsh &amp; Leonard Muellner.
  <em>DocBook - The Definitive Guide</em>. O&#8217;Reilly &amp; Associates. 1999.
  ISBN 1-56592-580-7.
</p>
</li>
</ul></div>
</div>
</div>
</div>
<div id="footnotes"><hr></div>
<div id="footer">
<div id="footer-text">
Last updated 2014-06-23 10:56:06 UTC
</div>
</div>
</body>
</html>