forked from fedora-java/howto
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathpackaging_maven_project.txt
175 lines (134 loc) · 5.74 KB
/
packaging_maven_project.txt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
[[packaging_maven_project]]
=== Packaging Maven project
This step by step guide will show you how to package Maven project. Let's start with
probably simplest spec file possible.
[source,spec,numbered]
------
include::maven_project/simplemaven.spec[]
------
The spec file above is a real world example how it may look like for simple Maven
project. Both `%build` and `%install` sections consist only of one line.
Another interesting lines:
[source,spec]
------
10: BuildRequires: maven-local
------
All Maven projects need to have BuildRequires on `maven-local`. They also need
to have Requires and BuildRequires on `jpackages-utils`, but build system adds
these automatically. Package maintainer doesn't need to list them explicitly.
[source,spec]
------
31: %dir %{_javadir}/%{name}
------
By default, resulting JAR files will be installed in `%{_javadir}/%{name}`,
therefore package needs to own this directory.
The build could fail from many reasons, but one probably most common is
build failure due to <<error_missing_dependency, missing dependencies>>
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's remove the dependencies from `pom.xml`.
.Remove dependencies from pom.xml
[source,spec]
------
...
%prep
%setup -q
# Add following lines to %prep section of a spec file
%pom_remove_dep :commons-io
%pom_remove_dep :junit
------
Package maintainer can use a wide variety of "`pom_`" macros for modifying
`pom.xml` files. See <<helper_macros, Macros for POM modification>> section for
more information.
Now try to build the project again. The build will fail with
<<error_compilation_failure, compilation failure>>.
Oops, another problem. This time Maven thought it had all the necessary dependencies, but Java
compiler thinks otherwise.
Now it's possible to either patch the source code not to depend on
missing libraries or to package them. Second approach is usually correct. It's not necessary to package every
dependency right away. Maintainer could package compile time dependencies first and keep the
rest for later (test dependencies, ...). But Maven needs to know that it shouldn't try to run tests now. This can be achieved by passing `-f` option to `%mvn_build` macro. Maven
will stop complaining about missing test scoped dependencies from now on.
[TIP]
======
Another major reason to disable the test phase is to speed up the local build
process. This can also be achieved by specifying an additional switch
`--without=tests` to the `fedpkg` or the `mock` tool instead of adding a switch
to `%mvn_build`.
Another switch `--without=javadoc` causes the build to skip Javadoc generation.
Note that to actually build the package with tests disabled you have to specify
the switch to `%mvn_build`.
======
[NOTE]
======
It is always recommended to run all available test suites during build. It greatly improves quality of the package.
======
We already have package which provides `commons-io:commons-io` artifact, let's add it to the `BuildRequires`. Also disable tests for now.
[source,spec]
------
BuildRequires: maven-local
BuildRequires: apache-commons-io
...
%prep
%setup -q
# Comment out following lines in %prep section
#%%pom_remove_dep :commons-io
#%%pom_remove_dep :junit
%build
# Skip tests for now, missing dependency junit:junit:4.11
%mvn_build -f
------
[TIP]
======
One can easily search for package which provides desired artifact. Try
`dnf repoquery --whatprovides 'mvn(commons-io:commons-io)'`, or see how to
<<querying_repositories,query repositories>>.
======
Now try to build the project one more time. The build should succeed now. Congrats, you managed to create an RPM from Maven project!
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 `%{_javadir}`.
This can be easily achieved with `%mvn_file` macro:
[source,spec]
------
%prep
%setup -q
%mvn_file : %{name}/%{name} %{name}
------
See <<mvn_file, Alternative JAR File Names>> section for more information.
Another quite common thing to do is adding aliases to Maven artifact. Try to run `rpm
-qp --provides` on your locally built RPM package:
[source,shell]
------
$ rpm -qp --provides simplemaven-1.0-1.fc21.noarch.rpm
mvn(com.example:simplemaven) = 1.0
simplemaven = 1.0-1.fc21
------
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'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.
.Add alias to Maven artifact
[source,spec]
------
%mvn_alias org.example:simplemaven simplemaven:simplemaven
------
See <<mvn_alias, Additional Mappings>> for more information on `%mvn_alias`.
Rebuild the pacakge and check `rpm -qp --provides` output again:
[source,shell]
------
$ rpm -qp --provides simplemaven-1.0-2.fc21.noarch.rpm
mvn(com.example:simplemaven) = 1.0
mvn(simplemaven:simplemaven) = 1.0
simplemaven = 1.0-2.fc21
------
Now it doesn't matter if some other package depends on either of these listed
artifact. Both dependencies will always be satisfied with your package.
NOTE: One could try to fix dependencies in all the dependent packages
instead of adding an alias to single package. It's almost always wrong thing to
do.