├── LICENSE
├── README.md
└── images
├── dependency_types.png
├── export_package.png
├── module_overview.png
├── module_types.png
├── named_unnamed_module.png
└── open_package.png
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2018 Tanya Fesenko
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | Java Modules (JPMS) Cheat Sheet
2 | ========
3 |
4 | Project Jigsaw, The Java Platform Module System (JPMS), Modularity, JSR 277, JSR 376... These are the names of one of the most significant features of Java 9. Modularity reduces the complexity of the system by providing:
5 | * Explicit dependencies
6 | * Clear interface
7 | * Strong encapsulation
8 |
9 | Modularity is also arguably one of the terrifying Java features of all times. Despite these numerous benefits, proper modules are still rare species in the Java world.
10 |
11 | The purpose of this cheat sheet is to show that modules in Java are friendly to us, developers, and easy to use. The [Module Declaration (module-info.java)](#module-declaration-module-infojava) section explains how to define modules. The [Module Path vs Class-Path](#module-path-vs-class-path) section will be helpful for people migrating existing non-modular applications to JPMS.
12 |
13 | Table of Contents
14 | -----------------
15 | [FAQ](#faq)
16 |
17 | [Module Declaration (module-info.java)](#module-declaration-module-infojava)
18 | * [Module Name and Minimal Module Declaration](#module-name-and-minimal-module-declaration)
19 | * [Dependencies](#modules-dependencies)
20 | * [API](#modules-api)
21 | * Other Stuff: [Services](#optional-services-for-di), [Annotations](#annotations-in-module-declarations), and [Formal grammar of the module declaration file](#formal-grammar-of-the-module-declaration-file)
22 |
23 | [Module Path vs Class Path](#module-path-vs-class-path)
24 | * [Types of Modules: Named and Unnamed](#types-of-modules-named-and-unnamed)
25 | * [Explicit Modules](#explicit-modules)
26 | * [Automatic Modules](#automatic-modules)
27 | * [Unnamed Module](#unnamed-module)
28 |
29 | [Resources](#resources)
30 |
31 | FAQ
32 | ========
33 | Here are some of important questions about support of old-style non-modular jar in Java 9+. It's better than what you think! :star2:
34 |
35 | ### Will my plain old jar (without a module declaration) work?
36 | ...and...
37 | ### Will my modularized jar work with dependencies which are not modularized yet?
38 | YES! and YES!
39 | But... if...:ballot_box_with_check:it's Java 9 friendly, *e.g.*, it doesn't use private API or split packages.
40 |
41 | Read more:
42 | :page_facing_up: Java 9 Migration Guide: The Seven Most Common Challenges: https://blog.codefx.org/java/java-9-migration-guide/
43 |
44 | In JPMS, you can convert existing non-modular jars into:
45 | * **Unnamed** modules, when passed on classpath;
46 | * Or, **automatic** modules, when passed on module path.
47 | See [Module Path vs Class Path](#module-path-vs-class-path).
48 |
49 |
50 | Module Declaration (`module-info.java`)
51 | ========
52 | A module declaration is a file which defines the dependency graph:
53 | * Dependencies: Which other modules this module depends on;
54 | * API: which parts of this module other modules can use: at compile time or at runtime.
55 |
56 | To create a module declaration:
57 | :heavy_check_mark: Create a file named `module-info.java`
58 | :heavy_check_mark: By convention, it should be placed at the root source folder, e.g., next to the `com` or `org` folders.
59 |
60 | 
61 |
62 | Module Name and Minimal Module Declaration
63 | --------
64 | A minimal module declaration defines its name:
65 | ```java
66 | module com.mycompany.myproject {
67 | }
68 | ```
69 |
70 |
71 | :bomb::boom: The module name must be globally unique - the name conflicts are prohibited. A recommended practice is to use a reverse-domain-name pattern |
72 |
73 |
74 |
75 | Module's Dependencies
76 | --------
77 | Dependencies are other modules this module needs for its work - it **requires** these modules.
78 | 
79 |
80 | ```java
81 | module com.mycompany.myproject { // the module name should be unique
82 |
83 | // dependency on `com.example.foo.bar` which must be present both at compile time AND runtime
84 | requires com.example.foo.bar;
85 |
86 | // transitive dependency: any module which requires current module will also *implicitly* depend on this dependency
87 | requires transitive com.kitties.bar;
88 |
89 | // optional dependency is mandatory at compile time, but optional at runtime
90 | requires static com.owls.foo;
91 | }
92 | ```
93 | Read more:
94 | :page_facing_up: Optional Dependencies: https://blog.codefx.org/java/module-system-optional-dependencies/
95 | :page_facing_up: Transitive Dependencies: https://blog.codefx.org/java/implied-readability/
96 |
97 |
98 | Module's API
99 | --------
100 | In pre-Java 9 world any public class was available everywhere and could be used by any other class. The "internal" packages were not in fact internal. With Java 9, module's contents are not available to the external classes by default; one must explicitly define what the module exposes to outside world so that other modules could use it either in compile time or via reflection. Module's API is now expressly specified in the module's declaration.
101 |
102 |
103 |
104 |
105 | |
106 | Compile Access |
107 | Reflection Access |
108 |
109 |
110 | What |
111 | By Whom |
112 | What |
113 | By Whom |
114 |
115 |
116 | Export Package |
117 | Unqualified |
118 | - Public and protected types in the package
119 | - Public and protected members of those types
|
120 | All Code |
121 | - Public and protected types in the package
122 | - Public and protected members of those types
|
123 | All Code |
124 |
125 |
126 | Qualified |
127 | Modules from the "to" clause |
128 | Modules from the "to" clause |
129 |
130 |
131 | Open Package |
132 | Unqualified |
133 | NO access |
134 | All Code |
135 | - All types in the package
136 | - And all their members
|
137 | All Code |
138 |
139 |
140 | Qualified |
141 | Modules from the "to" clause |
142 | Modules from the "to" clause |
143 |
144 |
145 |
146 |
147 |
148 | ### How to export or open a package
149 | A package can be exported or opened in
150 | * :smiley: Module declaration (`module-info.java` file). It's a recommended approach when you have control over this file.
151 | * :worried: Or, as a command line option, if you have no other choice.
152 |
153 |
154 |
155 | |
156 | Module Descriptor |
157 | Java Command Line Options |
158 |
159 |
160 | Export Package |
161 | Unqualified |
162 | exports packageName |
163 | n/a |
164 |
165 |
166 | Qualified |
167 | exports packageName to targetModule
168 |
ALL-UNNAMED is NOT allowed in the descriptor |
169 | --add-exports sourceModule/packageName=targetModule(,targetModule)*
170 | The target-module can be ALL-UNNAMED to export to all unnamed modules |
171 |
172 |
173 | Open Package |
174 | Unqualified |
175 | opens packageName |
176 | n/a |
177 |
178 |
179 | Qualified |
180 | opens packageName to targetModule |
181 | --add-opens sourceModule/packageName=targetModule(,targetModule)* |
182 |
183 |
184 |
185 |
186 | Read more:
187 | :page_facing_up: Java Platform, Standard Edition Tools Reference > Main Tools to Create and Build Applications > java: https://docs.oracle.com/javase/9/tools/java.htm#GUID-3B1CE181-CD30-4178-9602-230B800D4FAE__GUID-AC22D7B8-E3C4-4554-AE49-A62C9421AA7C
188 | :page_facing_up: Five Command Line Options To Hack The Java 9 Module System: https://blog.codefx.org/java/five-command-line-options-to-hack-the-java-9-module-system/
189 |
190 |
191 | ### Exported Packages
192 |
193 | The `exports` directive defines what this module exposes to other modules at runtime and compile time.
194 |
195 | 
196 | ```java
197 | module com.mycompany.myproject { // the module name should be unique
198 |
199 | // unqualified export => grants access to ALL other modules
200 | exports com.mycompany.myproject.foo;
201 |
202 | exports com.mycompany.myproject.foo.internal
203 | // having a "to" clause means that this is a **qualified export** => exports the package only to the friends of the current module - the modules specified in the `to` clause
204 | to com.example.x;
205 | exports com.mycompany.myproject.bar.internal to com.example.y, com.example.z;
206 |
207 | }
208 | ```
209 |
210 | ### Packages Open for Reflection
211 | The `opens` directive opens the module to the **outside** modules for the reflection. It's usually useful when using reflection-based frameworks such as Spring or Guice;
212 |
213 |
214 |
215 | :pencil2: As for the code from inside of the current module, it can still reflectively access all types and members from the module regardless whether they were opened or not |
216 |
217 |
218 |
219 | 
220 | ```java
221 | module com.mycompany.myproject { // the module name should be unique
222 |
223 | // `opens` the package for reflection to ALL other modules
224 | // * compile time: no access at all
225 | // * runtime: to all types, including private types, and all their members, including private ones
226 | opens com.mycompany.myproject.ollie;
227 |
228 | // a qualified `opens` directive - only modules from the `to` cause can access this package at runtime
229 | opens com.mycompany.myproject.ollie.internal to org.anothercompany.coolframework;
230 |
231 | // Also see a section about the open modules - a module which opens ALL its packages
232 | }
233 | ```
234 | #### Shortcut: an **open** module
235 | An open module `opens` all its packages. To define it, add the `open` modifier before the `module`:
236 | ```java
237 | open module com.mycompany.myproject {
238 | }
239 | ```
240 |
241 | Advanced: Services for DI
242 | --------
243 | Services implemented with use of `ServiceLoader` existed in Java well before Java 9. Their goal is to do decouple the interface and its implementation(s). Now, in Java 9, we can declare services and their usages in the `module-info.java`:
244 | Service consumer:
245 | ```java
246 | module com.mycompany.serviceconsumer {
247 | // Use an existing service. The implementation can be accessed in code by using the ServiceLoader
248 | uses com.example.foo.ServiceInterface;
249 | }
250 | ```
251 | Service provider:
252 | ```java
253 | module com.mycompany.service {
254 | // Register a new service implementation for com.example.foo.ServiceInterface
255 | provides com.example.foo.ServiceInterface
256 | with com.example.foo.ServiceImpl;
257 | }
258 | ```
259 |
260 |
261 |
262 | :pencil2: Service consumer and service provider can also be defined in the same module. |
263 |
264 |
265 | Read more:
266 | :page_facing_up: https://dzone.com/articles/java-9-kickoff-project-jigsaw-and-serviceloader-part-2
267 |
268 | Advanced: Annotations in Module Declarations
269 | --------
270 | Module declarations can also have annotations, *e.g.*, the `@Deprecated` annotations:
271 | ```
272 | /**
273 | * This module was replaced by a new module performing the same job much better!
274 | * @deprecated use {@link com.mycompany.newcoolmodule} instead.
275 | */
276 | @Deprecated
277 | module com.mycompany.oldmodule {}
278 | ```
279 |
280 | Advanced: The formal grammar of the module declaration file
281 | --------
282 | OK, open modules, annotations... What else? :coffee: A structure of a module declaration may seem too complicated. But it's not! Just see the grammar for module files (taken from section 7.7 of [Java 9 Language Specification](http://cr.openjdk.java.net/~mr/jigsaw/spec/java-se-9-jls-diffs.pdf)):
283 | ```yaml
284 | ModuleDeclaration:
285 | {Annotation} [open] module Identifier{.Identifier}
286 | { {ModuleDirective} }
287 |
288 | ModuleDirective:
289 | requires {RequiresModifier} ModuleName ;
290 | exports PackageName [to ModuleName {, ModuleName}] ;
291 | opens PackageName [to ModuleName {, ModuleName}] ;
292 | uses TypeName ;
293 | provides TypeName with TypeName {, TypeName} ;
294 |
295 | RequiresModifier:
296 | (one of)
297 | transitive static
298 |
299 | ModuleName:
300 | Identifier{.Identifier}
301 | ```
302 |
303 | Module Path vs Class Path
304 | ========
305 |
306 |
307 |
308 | |
309 | Command line |
310 | Modular JAR (JAR with a module-info.class) |
311 | Plain JAR |
312 |
313 |
314 | Module Path |
315 | --module-path modulepath
316 | -p modulepath
|
317 | Explicitly defined module |
318 | Automatic module |
319 |
320 |
321 | Classpath |
322 | --class-path classpath
323 | -classpath classpath
324 | -cp classpath
325 |
|
326 | Unnamed module |
327 | Unnamed module |
328 |
329 |
330 |
331 |
332 | You can mix module path and classpath!
333 |
334 | Read more:
335 | :page_facing_up: Java Platform, Standard Edition Tools Reference > Main Tools to Create and Build Applications > java: https://docs.oracle.com/javase/9/tools/java.htm#GUID-3B1CE181-CD30-4178-9602-230B800D4FAE__BABDJJFI
336 |
337 |
338 | Types of Modules: Named and Unnamed
339 | --------
340 | As you can see from the table above:
341 | * Everything on the module path, regardless whether it's a plain jar or a jar with a module-info, becomes a named module.
342 | * Similarly, everything on the classpath, regardless whether it's a plain jar or a jar with a module-info, becomes an unnamed module.
343 |
344 |
345 | In fact, there are three module types:
346 | * Named:
347 | * Explicit
348 | * Automatic
349 | * Unnamed
350 |
351 |
352 |
353 | Explicit Modules
354 | --------
355 | Explicit modules follow the rules for [Dependencies](#modules-dependencies) and [API](#modules-api) defined in its [Module Declaration (module-info.java)](#module-declaration-module-infojava)
356 |
357 | Automatic Modules
358 | --------
359 | Automatic modules are plain JARs (no module descriptor) on the module path.
360 |
361 |
362 | :pencil2: reads vs requires
363 | "Module1 reads Module2" means that Module1 can access types from Module2's exported packages.
364 | A module that requires another module also reads the other module. |
365 |
366 |
367 |
368 | As they don't have a `module-info.class`, this information will be calculated using the following rules:
369 |
370 | * **Name**: `Automatic-Module-Name` from `MANIFEST.MF` if it's present. Derived from the JAR name otherwise.
371 | * They can be referenced using this name;
372 | * See http://branchandbound.net/blog/java/2017/12/automatic-module-name/ for details;
373 | * For Eclipse plug-ins, see https://dev.eclipse.org/mhonarc/lists/cross-project-issues-dev/msg14888.html;
374 | * **Dependencies**:
375 | * It `requires transitive` all other resolved modules;
376 | * Reads the [`unnamed` module](#unnamed-module);
377 | * **API**:
378 | * Exports all its packages;
379 | * The module can be referenced in other modules' `module-info.java` using its calculated name.
380 |
381 | Unnamed Module
382 | --------
383 | Everything on the classpath becomes an unnamed module.
384 | * ~**Name**~: No name;
385 | * **Dependencies**:
386 | * Reads all other modules
387 | * Can read or open other`ALL-UNNAMED` in the [command line](#how-to-export-or-open-a-package)
388 | * **API**:
389 | * Because it does not have a name, it cannot be referenced in module-info.java.
390 | * Readable only by [automatic modules](#automatic-modules)
391 |
392 |
393 |
394 | Resources
395 | ========
396 | :page_facing_up: Java Language Specification. Chapter 7. Packages and Modules. https://docs.oracle.com/javase/specs/jls/se9/html/jls-7.html
397 | :books::heavy_dollar_sign: The Java Module System by Nicolai Parlog : https://www.manning.com/books/the-java-module-system
398 | Disclaimer: I was a manuscript reviewer of this book and, thus, got a free copy of it from Manning.
399 |
400 | :books::heavy_dollar_sign: Java 9 Modularity by Sander Mak, Paul Bakker: https://javamodularity.com/
401 | :page_facing_up: Understanding Java 9 Modules: https://www.oracle.com/corporate/features/understanding-java-9-modules.html
402 | :page_facing_up: Programming with Modularity and Project Jigsaw. A Tutorial Using the Latest Early Access Build https://www.infoq.com/articles/Latest-Project-Jigsaw-Usage-Tutorial
403 | :speaker: Sander Mak on the Java Module System: https://www.infoq.com/podcasts/Sander-Mak-module-system-Java9
404 | :movie_camera: Designing for Modularity with Java 9: https://www.youtube.com/watch?v=tamVhtV18dY
405 |
406 | Acknowledgments
407 | =========
408 | * Special thanks to [Vera Zvereva](https://www.linkedin.com/in/verazvereva) whose feedback was invaluable.
409 | * https://github.com/ajaxorg/ace/pull/3628
410 |
411 |
412 |
--------------------------------------------------------------------------------
/images/dependency_types.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tfesenko/Java-Modules-JPMS-CheatSheet/46fd80a242daef8ad3c4d753945efc233fa52e20/images/dependency_types.png
--------------------------------------------------------------------------------
/images/export_package.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tfesenko/Java-Modules-JPMS-CheatSheet/46fd80a242daef8ad3c4d753945efc233fa52e20/images/export_package.png
--------------------------------------------------------------------------------
/images/module_overview.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tfesenko/Java-Modules-JPMS-CheatSheet/46fd80a242daef8ad3c4d753945efc233fa52e20/images/module_overview.png
--------------------------------------------------------------------------------
/images/module_types.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tfesenko/Java-Modules-JPMS-CheatSheet/46fd80a242daef8ad3c4d753945efc233fa52e20/images/module_types.png
--------------------------------------------------------------------------------
/images/named_unnamed_module.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tfesenko/Java-Modules-JPMS-CheatSheet/46fd80a242daef8ad3c4d753945efc233fa52e20/images/named_unnamed_module.png
--------------------------------------------------------------------------------
/images/open_package.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tfesenko/Java-Modules-JPMS-CheatSheet/46fd80a242daef8ad3c4d753945efc233fa52e20/images/open_package.png
--------------------------------------------------------------------------------