├── .gitignore
├── LICENSE
├── README.md
├── build.sh
├── content
├── articles
│ ├── 2014-06-27-foobar.md
│ ├── 2014-09-14-libfx-0-1-1-released.md
│ ├── 2014-09-17-codefx-up-and-running.md
│ ├── 2014-09-22-decorator-pattern-saved-my-day.md
│ ├── 2014-09-25-workflows-refactoring.md
│ ├── 2014-09-30-decorator-pattern-java-8.md
│ ├── 2014-10-04-architecture-lost-years.md
│ ├── 2014-10-07-intention-revealing-code-java-8-optional.md
│ ├── 2014-10-18-design-optional.md
│ ├── 2014-10-22-why-isnt-optional-serializable.md
│ ├── 2014-10-26-concepts-serialization.md
│ ├── 2014-10-29-serialization-proxy-pattern.md
│ ├── 2014-11-02-serialize-optional.md
│ ├── 2014-11-09-lambdas-java-peek-hood.md
│ ├── 2014-11-13-javafx-sources-in-eclipse.md
│ ├── 2014-11-23-libfx-0-2-0-released.md
│ ├── 2014-11-28-use-listenerhandles.md
│ ├── 2014-12-03-multiple-return-statements.md
│ ├── 2014-12-08-instances-non-capturing-lambdas.md
│ ├── 2014-12-31-goodbye-2014.md
│ ├── 2015-01-01-hello-2015.md
│ ├── 2015-01-07-new-javadoc-tags.md
│ ├── 2015-01-15-everything-about-default-methods.md
│ ├── 2015-01-26-android-emulator-haxm-thinkpad-t440p.md
│ ├── 2015-02-15-value-based-classes.md
│ ├── 2015-02-26-interface-evolution-with-default-methods-methods.md
│ ├── 2015-03-09-test-collection-implementations-with-guava.md
│ ├── 2015-03-16-roll-your-own-pirate-elvis-operator.md
│ ├── 2015-03-26-agile-architecture.md
│ ├── 2015-04-10-interface-evolution-with-default-methods-interfaces.md
│ ├── 2015-04-17-getting-rid-of-anonymous-classes.md
│ ├── 2015-04-27-how-java-9-and-project-jigsaw-may-break-your-code.md
│ ├── 2015-05-02-libfx-0-2-1-released.md
│ ├── 2015-05-06-crafted-design.md
│ ├── 2015-05-11-first-release-of-jdeps-maven-plugin.md
│ ├── 2015-05-18-javafx-project-jigsaw-jep-253.md
│ ├── 2015-05-26-transforming-collections.md
│ ├── 2015-05-28-libfx-0-3-0-released.md
│ ├── 2015-06-18-motivation-goals-project-jigsaw.md
│ ├── 2015-06-30-features-project-jigsaw-java-9.md
│ ├── 2015-07-06-casting-in-java-8-and-beyond.md
│ ├── 2015-07-15-comment-your-fucking-code.md
│ ├── 2015-07-31-thoughts-on-comments.md
│ ├── 2015-08-04-all-about-project-jigsaw-on-infoq.md
│ ├── 2015-08-14-interview-about-comments-on-dzone.md
│ ├── 2015-08-14-the-road-to-valhalla.md
│ ├── 2015-08-27-stephen-colebourne-optional-a-strict-approach.md
│ ├── 2015-09-07-stream-performance.md
│ ├── 2015-09-18-stream-performance-your-ideas.md
│ ├── 2015-09-28-taxonomy-comments.md
│ ├── 2015-10-05-apache-jmeter-tutorial.md
│ ├── 2015-10-19-jar-hell.md
│ ├── 2015-10-26-will-there-be-module-hell.md
│ ├── 2015-11-05-javaone-2015-prepare-for-jdk-9.md
│ ├── 2015-11-09-javaone-2015-introduction-to-modular-development.md
│ ├── 2015-11-11-javaone-2015-advanced-modular-development.md
│ ├── 2015-11-13-javaone-2015-under-the-hood-of-project-jigsaw.md
│ ├── 2015-11-23-junit-lambda-prototype.md
│ ├── 2015-12-02-delay-of-java-9-release.md
│ ├── 2015-12-07-jdeps-maven-plugin-0-2.md
│ ├── 2015-12-25-jigsaw-hands-on-guide.md
│ ├── 2015-12-31-goodbye-2015.md
│ ├── 2016-01-03-hello-2016.md
│ ├── 2016-01-14-stream-findfirst-findany-reduce.md
│ ├── 2016-01-27-implied-readability.md
│ ├── 2016-02-08-comments-costs-benefits.md
│ ├── 2016-03-07-atom-on-gentoo.md
│ ├── 2016-03-17-seven-reasons-against-blogging.md
│ ├── 2016-04-26-doomed-code-review.md
│ ├── 2016-05-14-codefx-levels-up.md
│ ├── 2016-05-25-jeeconf-2016.md
│ ├── 2016-06-06-implement-equals-correctly.md
│ ├── 2016-06-13-implement-hashcode-correctly.md
│ ├── 2016-06-20-java-9-stream.md
│ ├── 2016-06-26-java-9-optional.md
│ ├── 2016-07-25-oh-no-forgot-streamiterate.md
│ ├── 2016-08-04-goodbye-disy-hello-sitepoint.md
│ ├── 2016-08-15-code-reviews-disy-part-1.md
│ ├── 2016-09-01-rebutting-5-common-stream-tropes.md
│ ├── 2016-09-05-ultimate-guide-java-9.md
│ ├── 2016-09-26-code-reviews-disy-part-2.md
│ ├── 2016-10-26-code-reviews-disy-part-3.md
│ ├── 2016-11-24-hello-world.md
│ ├── 2016-12-01-future-java-might-look-like.md
│ ├── 2016-12-07-whats-taking-long.md
│ ├── 2016-12-14-snapshots-gradle-maven-publish-plugin.md
│ ├── 2016-12-21-javaone-2016.md
│ ├── 2016-12-29-goodbye-2016.md
│ ├── 2017-01-01-hello-2017.md
│ ├── 2017-01-18-reflection-vs-encapsulation.md
│ ├── 2017-01-26-quo-vadis-scala.md
│ ├── 2017-01-31-why-elvis-should-not-visit-java.md
│ ├── 2017-02-13-repackaging-exceptions-streams.md
│ ├── 2017-04-03-module-system-optional-dependencies.md
│ ├── 2017-05-02-java-9-resources-talks-articles-blogs-books-courses.md
│ ├── 2017-07-17-jdeps-tutorial.md
│ ├── 2017-07-24-java-9-migration-guide.md
│ ├── 2017-08-14-planning-your-java-9-update.md
│ ├── 2017-09-11-five-command-line-options-hack-java-module-system.md
│ ├── 2017-09-27-unified-logging-with-the-xlog-option.md
│ ├── 2017-10-03-java-module-system-tutorial.md
│ ├── 2017-10-23-jsr-305-java-9.md
│ ├── 2017-11-16-java-10-var-type-inference.md
│ ├── 2017-12-18-maven-on-java-9.md
│ ├── 2017-12-31-goodbye-2017-hello-2018.md
│ ├── 2018-02-05-java-9-tutorial.md
│ ├── 2018-02-26-multi-release-jars-multiple-java-versions.md
│ ├── 2018-06-11-intersection-types-var.md
│ ├── 2018-06-18-tricks-var-anonymous-classes.md
│ ├── 2018-06-25-traits-var.md
│ ├── 2018-08-05-junit-5-architecture-jupiter.md
│ ├── 2018-08-05-junit-5-basics.md
│ ├── 2018-08-05-junit-5-disabled-conditions.md
│ ├── 2018-08-05-junit-5-dynamic-tests.md
│ ├── 2018-08-05-junit-5-extension-model.md
│ ├── 2018-08-05-junit-5-parameterized-tests.md
│ ├── 2018-08-05-junit-5-setup.md
│ ├── 2018-09-25-java-11-migration-guide.md
│ ├── 2018-10-15-http-2-api-tutorial.md
│ ├── 2018-10-22-reactive-http-2-requests-responses.md
│ ├── 2018-11-06-scripting-java-shebang.md
│ ├── 2018-11-12-java-11-gems.md
│ ├── 2019-03-04-teeing-collector.md
│ ├── 2019-03-18-java-12-guide.md
│ ├── 2019-05-13-jakarta-ee-javax-and-a-week-of-turmoil.md
│ ├── 2019-05-29-immutable-collections-in-java.md
│ ├── 2019-06-19-text-blocks.md
│ ├── 2019-07-11-enable-preview-language-features.md
│ ├── 2019-08-07-the-jpms-maturity-model.md
│ ├── 2019-08-16-switch-expressions.md
│ ├── 2019-09-15-application-class-data-sharing.md
│ ├── 2019-09-17-java-13-guide.md
│ ├── 2020-10-07-junit-pioneer-1-0.md
│ ├── 2020-11-04-java-16-stream-mapmulti.md
│ ├── 2020-11-16-stream-mapmulti-group.md
│ ├── 2020-12-10-Java-2077.md
│ ├── 2021-01-19-spring-boot-react-folders.md
│ ├── 2021-02-16-pattern-matchig.md
│ ├── 2021-02-23-type-patterns.md
│ ├── 2021-03-03-unix-domain-sockets.md
│ └── 2021-03-16-java-16-guide.md
├── talks
│ ├── best-practices.md
│ ├── comment-your-code.md
│ ├── expert-java-8.md
│ ├── java-9-migration.md
│ ├── java-after-n.md
│ ├── java-module-system.md
│ ├── java-next.md
│ ├── java-var.md
│ ├── java-x.md
│ ├── junit-5.md
│ └── junit-pioneer.md
└── videos
│ ├── 2016-12-06-interview-devoxx-be-2016.md
│ ├── 2017-03-29-nighthacking-javaland-2017.md
│ ├── 2017-09-20-impressions-javazone-2017.md
│ ├── 2017-09-21-welcome-java-9.md
│ ├── 2017-11-16-var-java-10.md
│ ├── 2018-09-20-effective-java-00-kickoff.md
│ ├── 2018-09-24-effective-java-01-static-factory-methods.md
│ ├── 2018-10-02-java-11-new-dawn.md
│ ├── 2018-10-09-effective-java-02-builders.md
│ ├── 2018-10-18-java-12-switch-expression.md
│ ├── 2018-10-24-robert-scholte-maven-3-4-5.md
│ ├── 2018-11-27-effective-java-03-utilities-04-singleton-05-dependency-injection.md
│ ├── 2019-02-24-java-12-experiments.md
│ ├── 2019-04-18-caliz-1-learning-graal.md
│ ├── 2019-05-01-caliz-2-wrapping-graal.md
│ ├── 2019-05-16-caliz-3-background-compilation.md
│ ├── 2019-05-26-jpms-sander-mak.md
│ ├── 2019-09-18-keynote-blip-code-one-2019.md
│ ├── 2020-04-07-oliver-drotbohm-modularity.md
│ ├── 2020-04-28-generics-1-basics.md
│ ├── 2021-01-26-jdk-news-1.md
│ ├── 2021-02-11-brian-goetz-25h.md
│ └── 2021-03-05-jdk-news-2.md
├── genealogists
├── pom.xml
└── src
│ └── main
│ ├── java
│ └── org
│ │ └── codefx
│ │ └── java_after_eight
│ │ └── genealogists
│ │ ├── package-info.java
│ │ ├── random
│ │ ├── RandomGenealogist.java
│ │ └── RandomGenealogistService.java
│ │ ├── repo
│ │ ├── RepoGenealogist.java
│ │ └── RepoGenealogistService.java
│ │ ├── silly
│ │ ├── SillyGenealogist.java
│ │ └── SillyGenealogistService.java
│ │ ├── tags
│ │ ├── TagGenealogist.java
│ │ └── TagGenealogistService.java
│ │ └── type
│ │ ├── TypeGenealogist.java
│ │ └── TypeGenealogistService.java
│ └── resources
│ └── META-INF
│ └── services
│ └── org.codefx.java_after_eight.genealogist.GenealogistService
├── genealogy
├── pom.xml
└── src
│ ├── main
│ └── java
│ │ └── org
│ │ └── codefx
│ │ └── java_after_eight
│ │ ├── Config.java
│ │ ├── Main.java
│ │ ├── ProcessDetails.java
│ │ ├── Utils.java
│ │ ├── genealogist
│ │ ├── Genealogist.java
│ │ ├── GenealogistService.java
│ │ ├── RelationType.java
│ │ └── TypedRelation.java
│ │ ├── genealogy
│ │ ├── Genealogy.java
│ │ ├── Relation.java
│ │ └── Weights.java
│ │ ├── post
│ │ ├── Article.java
│ │ ├── Content.java
│ │ ├── Description.java
│ │ ├── Post.java
│ │ ├── Repository.java
│ │ ├── Slug.java
│ │ ├── Tag.java
│ │ ├── Talk.java
│ │ ├── Title.java
│ │ ├── Video.java
│ │ ├── VideoSlug.java
│ │ └── factories
│ │ │ ├── ArticleFactory.java
│ │ │ ├── PostFactory.java
│ │ │ ├── RawFrontMatter.java
│ │ │ ├── RawPost.java
│ │ │ ├── TalkFactory.java
│ │ │ └── VideoFactory.java
│ │ └── recommendation
│ │ ├── Recommendation.java
│ │ └── Recommender.java
│ └── test
│ └── java
│ └── org
│ └── codefx
│ └── java_after_eight
│ ├── TextParserTests.java
│ ├── UtilsTests.java
│ ├── genealogy
│ ├── GenealogyTests.java
│ ├── RelationTestHelper.java
│ ├── RelationTests.java
│ └── WeightsTests.java
│ ├── post
│ ├── DescriptionTests.java
│ ├── PostTestHelper.java
│ ├── SlugTests.java
│ ├── TagTests.java
│ ├── TitleTests.java
│ └── factories
│ │ └── ArticleFactoryTests.java
│ └── recommendation
│ └── RecommenderTests.java
├── pom.xml
├── recommendations.config
├── run.sh
├── stats-code.sh
├── stats-time.sh
└── stats.sh
/.gitignore:
--------------------------------------------------------------------------------
1 | # Eclipse
2 |
3 | .metadata
4 | bin/
5 | tmp/
6 | *.tmp
7 | *.bak
8 | *.swp
9 | *~.nib
10 | local.properties
11 | .settings/
12 | .loadpath
13 | .recommenders
14 |
15 | .project
16 | .classpath
17 | *.launch
18 |
19 | # JetBrains
20 |
21 | .idea/
22 | *.iws
23 | *.iml
24 | /out/
25 |
26 | # Visual Studio Code
27 |
28 | .factoryPath
29 | .vscode/
30 |
31 | # Gradle
32 |
33 | .gradle/
34 | build/
35 |
36 | # Maven
37 |
38 | target/
39 | jars/
40 |
41 | # JVM crash logs
42 | # see http://www.java.com/en/download/help/error_hotspot.xml
43 | hs_err_pid*
44 |
45 | # Project
46 |
47 | recommendations.json
48 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Java After Eight/Eleven
2 |
3 | Nice Java 8/11 code base that gets way nicer with Java 9-19 and beyond.
4 |
5 | Code base for [my talk _Java After Eight/Eleven_](https://nipafx.dev/talk-java-after-n/).
6 | See the `java-$VERSION-guide.md` files [in the slides repo](https://github.com/nipafx/slides/tree/master/java-after-eight) to see which Java 9+ features go where.
7 | For a more structured approach to these features, check my [Java X demo repository](https://github.com/nipafx/demo-java-x).
8 |
--------------------------------------------------------------------------------
/build.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | set -e
3 |
4 | echo "building..."
5 | rm -f recommendations.json
6 | rm -rf jars/*
7 | mvn clean verify -q
8 |
--------------------------------------------------------------------------------
/content/articles/2014-06-27-foobar.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: "Foobar"
3 | tags: [meta, techniques]
4 | date: 2014-06-27
5 | slug: foobar
6 | description: "A foobar post that may accidentally teach you about Foobar."
7 | searchKeywords: "Foobar"
8 | featuredImage: foobar
9 | ---
10 |
11 | Sorry, but this is no real post.
12 | I just needed a first entry to enable the RSS feed...
13 |
14 | But if you couldn't tell by the post's name that it will contain nothing useful, then perhaps it's not so foobar after all.
15 | Read up on Foobar (e.g. [on Wikipedia](http://en.wikipedia.org/wiki/Foo)) and use it.
16 | Often!
17 | Every time you're standing in front of a whiteboard or programming with someone else and you need a name that your audience should not waste their mental energy on, pick one of these: `foobar`, `foo`, `bar`, `baz`, ...
18 |
19 | And in case you are not standing in front of a whiteboard or are not programming with someone else on a regular basis... well, you should change that, it's fun!
20 | 😉
21 |
--------------------------------------------------------------------------------
/content/articles/2014-09-14-libfx-0-1-1-released.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: "LibFX 0.1.1 Released"
3 | tags: [javafx, libfx]
4 | date: 2014-09-14
5 | slug: libfx-0-1-1
6 | description: "Release post for LibFX 0.1.1 including a description of `Nestings` and pointers to GitHub, Maven and the Javadoc."
7 | searchKeywords: "libfx"
8 | featuredImage: libfx-library
9 | repo: libfx
10 | ---
11 |
12 | Just today I released [LibFX 0.1.1](https://github.com/nipafx/LibFX/releases/tag/v0.1.1)!
13 |
14 | > That's one small step for everybody else, one giant leap for me.
15 |
16 | Or something like that...
17 | 😉
18 | It's surely no big deal for a seasoned open source developer but since it's the very first production-ready release of my very first own open source library, it feels like quite the accomplishment to me.
19 |
20 | So I am here to proudly present it!
21 |
22 | ## LibFX 0.1.1
23 |
24 | So what can **LibFX** do for you?
25 | Currently it has only one feature, namely *Nestings*.
26 | It is [described in detail in the project's wiki](https://github.com/nipafx/LibFX/wiki/Nestings) but I will give a quick introduction here.
27 |
28 |
29 |
30 | ### Nestings
31 |
32 | Nestings enhance JavaFX' properties with a neat way to capture object hierarchies.
33 | Imagine the model for your UI has an `ObjectProperty currentEmployee` and the employee has an `ObjectProperty addressProperty()` which in turn has a `StringProperty streetNameProperty()`.
34 |
35 | Now let's say you create an editor that you want to use to display and edit the current employee's street name.
36 | Note that the current employee can be replaced as well as the employee's address or the address' street name and of course you want your editor to always be up to date and point to the correct property.
37 |
38 | With the standard FX classes you are out of luck and essentially have to implement a lot of listening to property changes and updating bindings which will soon clutter your code.
39 |
40 | Enter **LibFX**!
41 | Using [method references](http://docs.oracle.com/javase/tutorial/java/javaOO/methodreferences.html) you can do this:
42 |
43 | ```java
44 | StringProperty currentEmployeesStreetName = Nestings
45 | .on(currentEmployeeProperty)
46 | .nest(Employee::addressProperty)
47 | .nest(Address::streetNameProperty)
48 | .buildProperty();
49 | ```
50 |
51 | Now you have a property which always points to current employee's current address' street name.
52 | This is a fully functional property so you can do all the usual things with it.
53 | In this case, you could bidirectionally bind the editor's value property to it and you're done!
54 |
55 | ## Infrastructure
56 |
57 | But as important and surely as work-intensive as the feature was the infrastructure.
58 | I finally got (almost) all the tools up and running.
59 |
60 | ### About LibFX
61 |
62 | The project is hosted on [GitHub](https://github.com/nipafx/LibFX), which also offers the awesome [GitHub Pages](https://pages.github.com/).
63 |
64 | They run the project page under [libfx.codefx.org](http://libfx.codefx.org), which is the central point for all information regarding **LibFX**.
65 | It links to all tools, services and resources involved in creating the library, which especially include the [wiki](https://github.com/nipafx/LibFX/wiki) and the [Javadoc](http://libfx.codefx.org/javadoc/).
66 |
67 | ### Maven Coordinates
68 |
69 | LibFX 0.1.1 is available in Maven Central and these are the coordinates:
70 |
71 | ```xml
72 | org.codefx.libfx
73 | LibFX
74 | 0.1.1
75 | ```
76 |
77 | Maven Central provides [further information for **LibFX** 0.1.1](http://search.maven.org/#artifactdetails%7Corg.codefx.libfx%7CLibFX%7C0.1.1%7Cjar), which can be used for other build tools.
78 |
79 | ### Continuous Inspection and Integration
80 |
81 | As far as I can tell at the moment, these are the only pieces missing to the puzzle.
82 | I don't think continuous integration is very important at this stage of the project but I'm curious and would like to get to know it before it really counts.
83 |
84 | But what I really crave is [SonarQube](http://www.sonarqube.org/)!
85 | I want it badly!
86 | But I'm still looking for a way to get it without breaking my budget.
87 | As soon as I find one I'll fix every possible issue and be back here to brag about the code quality.
88 | 😁
89 |
--------------------------------------------------------------------------------
/content/articles/2014-09-17-codefx-up-and-running.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: "CodeFX Up And Running"
3 | tags: [meta]
4 | date: 2014-09-17
5 | slug: codefx-up-and-running
6 | description: "Summer recess is officially over and shit got done! Finally, CodeFX is ready to take on the world."
7 | searchKeywords: "CodeFX"
8 | featuredImage: codefx-up-and-running
9 | ---
10 |
11 |
12 |
13 | This post is _old_ and almost everything it touches on changed since then - starting with CodeFX, which is now nipafx (hey, that's me!).
14 | Such are the woes of the internet.
15 | 😁
16 |
17 |
18 |
19 | ## Up
20 |
21 | Besides starting my new day job, I finished some long waiting coding and infrastructure work.
22 |
23 | ### Code
24 |
25 | I cleaned up my *SnapshotView* over at [ControlsFX](https://controlsfx.org) (which is currently waiting to be pulled) and finally got everything working to [release the first production-ready version of LibFX](libfx-0-1-1).
26 |
27 | ### CodeFX
28 |
29 | Maybe even more important in this context is that I finally got this blog ready to go!
30 | I tweaked the theme (and hope everybody reacts to the Eclipse purple I recklessly plagiarized) and got some much needed plugins like the very cool [Crayon](https://wordpress.org/plugins/crayon-syntax-highlighter/) which paints my code like this:
31 |
32 | ```java
33 | StringProperty currentEmployeesStreetName = Nestings
34 | .on(currentEmployeeProperty)
35 | .nest(Employee::addressProperty)
36 | .nest(Address::streetNameProperty)
37 | .buildProperty();
38 | ```
39 |
40 | Foregoing the neither pretty nor overly usable WordPress comments I looked for another way to lure you, the reader, into a conversation.
41 | I would've liked to go for [Discourse](https://www.discourse.org/) but couldn't find a cheap (read: for free) way to run it.
42 | Who knows, if this blog takes off, I might spend some money on it after all.
43 |
44 | But for now we're going with [Disqus](https://disqus.com/).
45 | To keep the site loading fast, comments are only loaded on demand (see the button at the end of this post) and in case you already have a Disqus account you can of course use it here as well.
46 |
47 | Finally, I'm done fighting with newsletter plugins, be it *Mailpoet*, *Newsletter Ready!* or *Newsletter* (ha, no links for you!).
48 | I'm sticking with the latter and since it doesn't provide a convenient way to send out complete posts, you won't get them via the newsletter.
49 | So if you want to read without stopping by, you'll have to [subscribe to the RSS feed](/feed.xml).
50 |
51 | ## Running
52 |
53 | So now that everything's done there are no more excuses.
54 | I'm ready to [achieve ultimate blog success in one easy step](https://blog.codinghorror.com/how-to-achieve-ultimate-blog-success-in-one-easy-step/)!
55 | ☺️
56 |
57 | And look at that, I even have some ideas of (interesting?) things to write about!
58 | Like a tutorial on creating a first open source project - something I recently went through myself.
59 | Or how to create a JavaFX control the way it's supposed to be done...
60 |
61 | So I’ll be back and I hope so will you!
62 |
--------------------------------------------------------------------------------
/content/articles/2014-10-04-architecture-lost-years.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: "Impulse: \"Architecture - The Lost Years\""
3 | tags: [architecture, impulse]
4 | date: 2014-10-04
5 | slug: architecture-lost-years
6 | description: "Discussing the talk \"Architecture - The Lost Years\", which Robert C. Martin held on several occasions."
7 | searchKeywords: "Architecture Lost Years"
8 | featuredImage: architecture-lost-years
9 | ---
10 |
11 | Wow!
12 |
13 | There's not much more to say.
14 | The architecture Robert C.
15 | Martin presents in [this talk](http://www.youtube.com/watch?v=WpkDN78P884 "Robert C. Martin at Ruby Midwest 2011") is mind-blowing.
16 | Never mind that it's 20 years old - nobody seems to use it so it counts as new.
17 | (By the way those are the lost years in the title "Architecture - The Lost Years".)
18 |
19 | Just go and watch the video!
20 |
21 | I'll not even try to properly summarize the talk as I think it should be watched in its entirety.
22 | But just in case you wonder whether you really want to do that, I'll try to make you curious.
23 |
24 | ## The Talk
25 |
26 | ([Link to YouTube](http://www.youtube.com/watch?v=WpkDN78P884 "Robert C. Martin at Ruby Midwest 2011"))
27 |
28 | Just in case you want to watch it again, use [this link](http://www.youtube.com/watch?v=asLUTiJJqdE "Robert C. Martin at COHAA").
29 | It doesn't have the slides but a fun introduction about lasers.
30 |
31 | Unfortunately I couldn't find the slides online.
32 | In case you do, you can link them in the comments.
33 |
34 | ## Making You Curious
35 |
36 | The following summary has a big hole in it where the actual architecture is described.
37 | But the rest is more or less there.
38 |
39 | ### Folder Structure
40 |
41 | Martin starts with showing a standard Ruby on Rails app.
42 | And while the used framework is obvious from the code's top level folders, the actual intent of the program is not.
43 | But shouldn't it be?
44 |
45 | > Architecture of an application is all about its intent.
46 |
47 | He compares that with building architecture where the ground plan will clearly give away the building's purpose.
48 | For code the ground plan would be the content of the topmost folder, maybe the ones below that.
49 | So, likewise, these folders should clearly show the code's purpose.
50 | And they should do this by listing the use cases so there should be folders like *CreateOrder* and *AddItemToOrder*.
51 |
52 | Does your code look like that?
53 | Mine doesn't.
54 |
55 | ### Details
56 |
57 | He also mentions two things which should be an implementation detail in properly architectured systems:
58 |
59 | - the user interface
60 | - the database
61 |
62 | The former not only includes the UI technology but also (and especially) the Web.
63 | That's just a delivery mechanism to get the user in touch with the business logic!
64 | It should in no way be of any importance to the system's architecture.
65 |
66 | And the database is also something that dangles off the side of your application.
67 | It's a mere implementation detail.
68 |
69 | If all that doesn't make you curious, you're either really good or very unexcitable.
70 |
71 | ### Use Case Driven Design
72 |
73 | So how to achieve all that?
74 | With the [use case driven approach presented by Ivar Jacobson](https://www.amazon.com/dp/0201544350) in 1993.
75 | (There also exists a [slimmed down, updated and free version](http://www.ivarjacobson.com/download.ashx?id=1282) from 2011.)
76 |
77 | Martin goes on to explain the concept.
78 |
79 | I'm not going to summarize that part.
80 | It is too complex and important to be cramped into a few lines.
81 | I'm currently thinking about writing a small app just to test drive the concept.
82 | If I do, I might make some posts out of my experience, so stay tuned: [⇒ newsletter](news), [⇒ RSS](/feed.xml)
83 |
84 |
85 |
86 | At GeeCON 2014 Sandro Mancuso gave a talk called *Crafted Design*.
87 | It is based on the same observation and problem statement as Martin's talk and comes to a very similar solution.
88 | I covered it in my post [Impulse: "Crafted Design"](crafted-design) and it contains a description of the architecture, which I did not write here.
89 | You should check it out!*
90 |
91 |
92 |
93 | ### Effects
94 |
95 | Martin mentions two major advantages of such an approach.
96 |
97 | #### Good Architecture
98 |
99 | If you ban all subsystems which are not part of the central business logic to the outer reaches of your code and abstract them behind interfaces, you can easily substitute them.
100 | This leads to good architecture as Martin defines it:
101 |
102 | > A good architecture allows major decisions to be deferred!
103 |
104 | > A good architecture maximized the number of decisions not made.
105 |
106 | He gives [FitNesse](http://www.fitnesse.org/) as an example.
107 | It was supposed to get a database to persist its content - in fact this was one of the first things the team considered.
108 | But for no special reason they deferred that decision a couple of times.
109 | Eventually, the system was ready and still had no database because, as it turns out, it was not necessary.
110 | And when a customer really needed one, it was plugged in without effort.
111 |
112 | #### Testing
113 |
114 | Of course no talk by Martin would be complete without him insisting on having a comprehensive and fast test suite.
115 | He quickly outlines why this is so important: If you can't test everything and do it fast, you won't refactor constantly, in which case you're doomed.
116 | (Yes, it's that simple.)
117 |
118 | But keeping tests fast is impossible if they typically involve the database or the UI.
119 | Unfortunately, this is the reality for many systems as those subsystems are not sufficiently decoupled to be substituted with mocks during tests.
120 |
121 | Jacobson's approach, on the other hand, promotes exactly that kind of decoupling.
122 | If the UI, database, file system, online services and whoknowswhatelse all become plugins, you can mock them easily and have your tests run blazingly fast.
123 |
124 | ## Reflection
125 |
126 | As I didn't cover the main part of the talk, we can't reflect on that.
127 | Instead, I'm going to insist some more:
128 |
129 | - [watch the talk](https://www.youtube.com/watch?v=WpkDN78P884 "Robert C.
130 | Martin at Ruby Midwest 2011")
131 | - [or this one](https://www.youtube.com/watch?v=asLUTiJJqdE "Robert C.
132 | Martin at COHAA")
133 | - [or this one](https://www.youtube.com/watch?v=HhNIttd87xs "Robert C.
134 | Martin at Hakka Labs")
135 | - [or this one](https://www.youtube.com/watch?v=Nltqi7ODZTM "Robert C.
136 | Martin at NDC 2012") (looks like he's been touring)
137 | - [get the original book by Jacobosn](https://www.amazon.com/dp/0201544350)
138 | - [get the updated version](http://www.ivarjacobson.com/download.ashx?id=1282)
139 | - try it out
140 | - give me your opinion
141 |
142 |
--------------------------------------------------------------------------------
/content/articles/2014-11-13-javafx-sources-in-eclipse.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: "JavaFX Sources in Eclipse"
3 | tags: [tools, javafx]
4 | date: 2014-11-13
5 | slug: javafx-sources-in-eclipse
6 | description: "A quick step by step guide how to use the JavaFX sources in Eclipse by attaching them to the current JDK."
7 | searchKeywords: "JavaFX sources in eclipse"
8 | featuredImage: javafx-with-attached-source
9 | ---
10 |
11 | Just a quickie about how to tell Eclipse to attach the JavaFX sources for an improved development experience.
12 |
13 | ## Java Sources
14 |
15 | When you're using [Eclipse](http://eclipse.org/) with a JDK as your system library, the IDE will helpfully display [Javadoc](https://en.wikipedia.org/wiki/Javadoc) when you hover over members of official Java classes and let you jump into the code whenever you want to.
16 | This is extremely helpful to get to know the classes and take a look at their inner workings.
17 |
18 | This is possible because the JDK comes with its own sources and Eclipse knows about them.
19 | It attaches those sources to the compiled classes from the JDK and thus provides you those benefits.
20 |
21 | ## JavaFX Sources
22 |
23 | For reasons unknown to me, Eclipse does not automatically do this for the JavaFX classes (from the package `javafx` ), though.
24 | But because like the rest of the JRE, the FX sources are also bundled with the JDK, few things are easier than to attach them.
25 |
26 | In Eclipse:
27 |
28 | 1. open preferences (*Window* \~> *Preferences*)
29 | 2. edit the used JRE (*Java* \~> *Installed JREs* \~> Select JDK on the right \~> *Edit*)
30 | 3. start to attach FX sources (select **jfxrt.jar** \~> *Source Attachement)*
31 | 4. configure the sources (select *External location* \~> *External File*)
32 | 5. select the sources bundled with the JDK
33 |
34 | (go to JDK root folder, e.g. C:/Program Files/Java/jdk1.8.0\_20
35 |
36 | \~> select **javafx-src.zip**)
37 |
38 | 6. almost done, just OK/Finish your way back...
39 |
40 | To verify that this worked, open the *Open Type* dialog (by default with *Ctrl-Shift-T*) and check that you can open types from JavaFX like `javafx.application.Application`, `javafx.application.Platform` or `javafx.beans.property.Property`.
41 |
42 | You should also be able to see tooltips like this one:
43 |
44 | ## Reflection
45 |
46 | You have seen a step by step guide how to attach the JavaFX sources in Eclipse so it shows the Javadoc and lets you jump into the source code.
47 |
48 | Last step: Have even more fun with JavaFX!
49 |
--------------------------------------------------------------------------------
/content/articles/2014-11-23-libfx-0-2-0-released.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: "LibFX 0.2.0 Released"
3 | tags: [javafx, libfx]
4 | date: 2014-11-23
5 | slug: libfx-0-2-0
6 | description: "Release post for LibFX 0.2.0 including and pointers to GitHub, Feature descriptions, Maven coordinates and the Javadoc."
7 | searchKeywords: "libfx 0.2.0"
8 | featuredImage: libfx-library
9 | repo: libfx
10 | ---
11 |
12 | Yesterdays I released [**LibFX 0.2.0**](https://github.com/nipafx/LibFX/releases/tag/v0.2.0)!
13 | It has nice new features I've been needing for other projects:
14 |
15 | - [`ControlPropertyListener`](https://github.com/nipafx/LibFX/wiki/ControlPropertyListener): creating listeners for the property map of JavaFX' controls
16 | - [`ListenerHandle`](https://github.com/nipafx/LibFX/wiki/ListenerHandle): encapsulating an observable and a listener for easier add/remove of the listener
17 | - [`SerializableOptional`](https://github.com/nipafx/LibFX/wiki/SerializableOptional): serializable wrapper for `Optional`
18 | - [`WebViewHyperlinkListener`](https://github.com/nipafx/LibFX/wiki/WebViewHyperlinkListener): add hyperlink listeners to JavaFX' `WebView`
19 |
20 | And don't forget about [Nestings](https://github.com/nipafx/LibFX/wiki/Nestings): using all the power of JavaFX' properties for nested object aggregations.
21 |
22 | ## Getting Started
23 |
24 | The links above point to the [**LibFX** wiki on GitHub](https://github.com/nipafx/LibFX/wiki).
25 | It has an article for each feature explaining the concept, giving some examples and pointing to the best resource in the code to get started.
26 |
27 | Most key features also have self-contained demos, which can be found in [their own source folder](https://github.com/nipafx/LibFX/tree/master/src/demo/java/org/codefx/libfx).
28 |
29 | Finally, there's extensive Javadoc under [libfx.codefx.org/javadoc/](http://libfx.codefx.org/javadoc/).
30 |
31 | ## Getting LibFX 0.2.0
32 |
33 | You can get **LibFX 0.2.0** here:
34 |
35 |
36 |
37 | ```xml
38 |
39 | org.codefx.libfx
40 | LibFX
41 | 0.2.0
42 |
43 | ```
44 |
45 | ```java
46 | compile 'org.codefx.libfx:LibFX:0.2.0'
47 | ```
48 |
49 | It's licensed under GLP 3.0 but other arrangements can be made - just [shoot me an email](mailto:nicolai@nipafx.dev).
50 |
--------------------------------------------------------------------------------
/content/articles/2015-01-26-android-emulator-haxm-thinkpad-t440p.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: "Running Android Emulator With HAXM On Thinkpad T440p"
3 | tags: [tools]
4 | date: 2015-01-26
5 | slug: android-emulator-haxm-thinkpad-t440p
6 | description: "Quick guide to how to use the Android emulator with HAXM (based on VT-x) on a Thinkpad T440p."
7 | searchKeywords: "HAXM"
8 | featuredImage: haxm
9 | ---
10 |
11 | Over the weekend, I started to work on [my first Android app](https://github.com/CodeFX-org/privacy-guide).
12 | I had a little trouble getting the [Android emulator](http://developer.android.com/tools/devices/index.html) to run with *HAXM*, Intel's *Hardware Accelerated Execution Manager*, which builds on top of the virtualization hardware *VT-x*.
13 | Maybe others with the same problems find their way here...
14 |
15 | These are the steps that worked **for me** - your mileage may vary.
16 | Read them carefully; I might have let my frustration slip into the steps at some point or other.
17 |
18 | ## Hardware Support
19 |
20 | First check whether your processor actually supports virtualization.
21 |
22 | 1. [go to Intel](http://ark.intel.com/)
23 | 2. find your processor
24 | 3. check whether *Intel® Virtualization Technology (VT-x)* is listed under *Advanced Technologies*
25 | 4. also read the footnote if there is one
26 |
27 | Side note: [*VT-x* is included in *VT-d*](https://software.intel.com/en-us/articles/intel-virtualization-technology-for-directed-io-vt-d-enhancing-intel-platforms-for-efficient-virtualization-of-io-devices)
28 |
29 | ## Download _HAXM_ installer
30 |
31 | Now you can download the installer for the emulator accelerator.
32 |
33 | 1. open the Android SDK Manager
34 | - in Android Studio it's under *Tools* \~> *Android* \~> *SDK Manager*
35 | - in Eclipse it's under *Window* \~> *Android SDK Manager* (look [here](http://stackoverflow.com/a/13885869/2525313) if it's missing)
36 | 2. check *Intel x86 Emulator Accelerator (HAXM installer)* under *Extras* and install packages
37 |
38 | ## Install _HAXM_
39 |
40 | Next step is to actually install HAXM.
41 |
42 | 1. above the package list the SDK manager shows the path to the SDK
43 | 2. go there and then continue to *./extras/intel/Hardware\_Accelerated\_Execution\_Manager*
44 | 3. run the *intelhaxm-android* installer
45 |
46 | ## Fail In Different Ways (optional)
47 |
48 | In case the installation doesn't work because the virtualization features are not turned on, there are several ways to waste some time...
49 |
50 | 1. you can download intel's Processor Identification Utility (for [Windows](https://downloadcenter.intel.com/Detail_Desc.aspx?DwnldID=7838) and [Linux](http://www.intel.com/support/processors/tools/piu/sb/CS-033142.htm)) and see it claim that *Intel (R) Virtualization Technology* is *Yes* (not my wording)
51 | 2. you can install [CPU-Z](http://www.cpuid.com/softwares/cpu-z.html) or [i-Nex](http://www.omgubuntu.co.uk/2014/02/nex-cpu-z-hardware-stat-tool-linux) and watch it report *VT-X* (under *instructions*) to be turned on
52 |
53 | ## Fix It
54 |
55 | After that small detour you might realize that the tools are lying to you...
56 |
57 | 1. enter your BIOS (on my T440p: *Enter* on first boot screen, then *F1*)
58 | 2. go to *Config* \~> *CPU* and be frustrated that it's not there...
59 | 3. go to *Security* \~> *Virtualization* and turn everything on
60 | 4. reboot and install successfully
61 |
62 | ## Some more links...
63 |
64 | - [Speeding Up the Android Emulator on Intel Architecture - Intel](https://software.intel.com/en-us/android/articles/speeding-up-the-android-emulator-on-intel-architecture)
65 | - [HAXM Install Will Not Detect Enabled VT-x - thread in Intel forum](https://software.intel.com/en-us/forums/topic/328242)
66 | - [active *Hyper-V* might lock access to *VT-x*](https://forums.lenovo.com/t5/T400-T500-and-newer-T-series/Intel-VT-x-on-T440-64-bit-Virtual-Machine-Support/m-p/1639600/highlight/true#M100150 "Intel VT-x on T440?
67 | (64-bit Virtual Machine Support) - Lenovo Forum")
68 |
69 | Worked?
70 | Didn't work?
71 | Tweet, leave a comment, shoot me a mail...
72 |
--------------------------------------------------------------------------------
/content/articles/2015-05-02-libfx-0-2-1-released.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: "LibFX 0.2.1 Released"
3 | tags: [libfx]
4 | date: 2015-05-02
5 | slug: libfx-0-2-1
6 | description: "Release post for LibFX 0.2.1 including pointers to GitHub, feature descriptions, Maven coordinates and the Javadoc."
7 | searchKeywords: "libfx 0.2.1"
8 | featuredImage: libfx-library
9 | repo: libfx
10 | ---
11 |
12 | I released [**LibFX 0.2.1**](https://github.com/nipafx/LibFX/releases/tag/v0.2.1) yesterday!
13 | It contains a bugfix in [Nestings](https://github.com/nipafx/LibFX/wiki/Nestings).
14 |
15 | ## Getting Started
16 |
17 | If you want to find out about **LibFX** check out the [wiki on GitHub](https://github.com/nipafx/LibFX/wiki).
18 | It has an article for each feature explaining the concept, giving some examples and pointing to the best resource in the code to get started.
19 |
20 | Most key features also have self-contained demos, which can be found in [their own source folder](https://github.com/nipafx/LibFX/tree/master/src/demo/java/org/codefx/libfx).
21 |
22 | Finally, there's extensive Javadoc under [libfx.codefx.org/javadoc](http://libfx.codefx.org/javadoc).
23 |
24 | ## Getting LibFX 0.2.1
25 |
26 | You can get **LibFX 0.2.1** here:
27 |
28 |
29 |
30 | ```xml
31 |
32 | org.codefx.libfx
33 | LibFX
34 | 0.2.1
35 |
36 | ```
37 |
38 | ```groovy
39 | compile 'org.codefx.libfx:LibFX:0.2.1'
40 | ```
41 |
42 | **LibFX** is licensed under GLP 3.0 but other arrangements can be made - just [shoot me an email](mailto:nicolai@nipafx.dev).
43 |
--------------------------------------------------------------------------------
/content/articles/2015-05-11-first-release-of-jdeps-maven-plugin.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: "First Release of JDeps Maven Plugin"
3 | tags: [java-9, jdeps, tools, project-jigsaw]
4 | date: 2015-05-11
5 | slug: jdeps-maven-plugin-0-1
6 | description: "The JDeps Maven Plugin will break a project's build if it contains dependencies on JDK-internal APIs. This helps to prepare for Java 9."
7 | intro: "The JDeps Maven Plugin will break a project's build if it contains dependencies on JDK-internal APIs. This helps to prepare for Java 9, where these dependencies will be unaccessible."
8 | searchKeywords: "JDeps Maven Plugin"
9 | featuredImage: jdeps-mvn-motor
10 | repo: jdeps-maven-plugin
11 | ---
12 |
13 | Two weeks ago I wrote about [how Java 9 may break your code](how-java-9-and-project-jigsaw-may-break-your-code).
14 | A substantial obstacle for the transition to Java 9 can be a project's dependencies on JDK-internal APIs.
15 | These will be unaccessible in the new Java version and code containing them will not compile.
16 | It is hence important to weed them out in the remaining time.
17 | (Btw, Java 9 is [scheduled for September 2016](http://mail.openjdk.java.net/pipermail/jdk9-dev/2015-May/002172.html).)
18 |
19 | To help our projects (and maybe yours) with that, I created the [*JDeps Maven Plugin*](https://github.com/nipafx/JDeps-Maven-Plugin).
20 | It breaks the build if the code contains any problematic dependencies.
21 |
22 | ## JDeps
23 |
24 | To help identify problematic dependencies the JDK 8 contains the [Java Dependency Analysis tool *jdeps*](https://docs.oracle.com/javase/8/docs/technotes/tools/unix/jdeps.html).
25 | Run against a jar, a folder or a single class it will analyze and output dependencies.
26 | Analysis and output can be configured with several command line options.
27 |
28 | Run as `jdeps -jdkinternals` it will only list the dependencies on JDK-internal API.
29 | Exactly these dependencies are the ones that would break if compiled against Java 9.
30 | It is hence the basis of the Maven plugin.
31 |
32 | ## JDeps Maven Plugin
33 |
34 | The plugin runs `jdeps -jdkinternals` against the compiled classes, parses the output and breaks the build if it contained any dependencies.
35 |
36 |
37 |
38 | ### Configuration
39 |
40 | To use it in a project include this in its pom:
41 |
42 | ```xml
43 |
44 |
45 | ...
46 |
47 | org.codefx.maven.plugin
48 | jdeps-maven-plugin
49 | 0.1
50 |
51 |
52 |
53 | jdkinternals
54 |
55 |
56 |
57 |
58 | ...
59 |
60 |
61 | ```
62 |
63 | The plugin is extremely simple and the current version neither allows nor requires any further configuration.
64 |
65 | ### Execution
66 |
67 | The plugin will be executed during [the verify phase](https://maven.apache.org/guides/introduction/introduction-to-the-lifecycle.html).
68 | It will hence run in a full build with `mvn verify` (or any later phase).
69 | With `mvn jdeps:jdkinternals` it can be run directly.
70 |
71 | If your project contains any internal dependencies the build will fail with a message like this:
72 |
73 | ```
74 | [ERROR] Failed to execute goal
75 | org.codefx.maven.plugin:jdeps-maven-plugin:0.1:jdkinternals
76 | (default-cli) on project MavenLab:
77 | [ERROR] Some classes contain dependencies on JDK-internal API:
78 | [ERROR] . org.codefx.lab.ExampleClass
79 | [ERROR] . -> sun.misc.BASE64Decoder [JDK internal API, rt.jar]
80 | [ERROR] . -> sun.misc.Unsafe [JDK internal API, rt.jar]
81 | [ERROR] . org.codefx.lab.AnotherExampleClass
82 | [ERROR] . -> sun.misc.Unsafe [JDK internal API, rt.jar]
83 | [ERROR] . org.codefx.lab.foo.ExampleClassInAnotherPackage
84 | [ERROR] . -> sun.misc.BASE64Decoder [JDK internal API, rt.jar]
85 | ```
86 |
87 | ### Roadmap
88 |
89 | The plugin fulfills the minimum requirements to be useful: it breaks the build if JDeps discovers any dependencies on JDK-internal APIs.
90 | But this may be inconvenient for larger projects which might already contain some.
91 | It would be nice to be able to configure the plugin so that it ignores certain known dependencies.
92 |
93 | This is the next step.
94 | A simple configuration consisting of elements of the form `org.codefx.lab.ExampleClass -> sun.misc.*` will allow to ignore certain dependencies.
95 | The plugin can hence be included in any build and be configured such that it only breaks when new dependencies are introduced.
96 |
97 | You can track the progress in [this issue](https://github.com/nipafx/JDeps-Maven-Plugin/issues/1).
98 |
99 | ## Existing Plugins
100 |
101 | There are (at least) two Maven plugins which allow to use JDeps.
102 |
103 | **[Maven JDeps by Philippe Marschall](https://github.com/marschall/jdeps-maven-plugin)**:
104 | Runs JDeps against the compiled classes and either prints the output or creates a report from it.
105 | Has no consequences for the build.
106 |
107 | **[Apache Maven JDeps](http://maven.apache.org/plugins-archives/maven-jdeps-plugin-LATEST/maven-jdeps-plugin/)**:
108 | In development.
109 | Seems to be aimed at breaking the build when discovering internal dependencies but this does currently not work.
110 |
111 | I wanted fast results and full control over where this is going for my projects.
112 | I hence decided to reimplement parts of the functionality.
113 |
114 | If this JDeps Maven plugin proves to be useful I will reach out and try to get some code included in either of those plugins (most likely the official one from Apache).
115 |
--------------------------------------------------------------------------------
/content/articles/2015-05-28-libfx-0-3-0-released.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: "LibFX 0.3.0 Released"
3 | tags: [libfx]
4 | date: 2015-05-28
5 | slug: libfx-0-3-0
6 | description: "Release post for LibFX 0.3.0 including pointers to GitHub, feature descriptions, Maven coordinates and the Javadoc."
7 | searchKeywords: "libfx 0.3.0"
8 | featuredImage: libfx-library
9 | repo: libfx
10 | ---
11 |
12 | I just released [**LibFX 0.3.0**](https://github.com/nipafx/LibFX/releases/tag/v0.3.0)!
13 |
14 | ## Features
15 |
16 | The killer feature are [transforming collections](https://github.com/nipafx/LibFX/wiki/TransformingCollections) about which I already [blogged a few days ago](java-transforming-collections).
17 | I also created an easy way to stream nodes of all kinds of trees.
18 | (I didn't get around to write up a wiki page for it yet but when I do, you will find it [here](https://github.com/nipafx/LibFX/wiki/TreeStreams).)
19 |
20 | And don't forget about the other features:
21 |
22 | **[ControlPropertyListener](https://github.com/nipafx/LibFX/wiki/ControlPropertyListener)**:
23 | Creating listeners for the property map of JavaFX' controls.
24 |
25 | **[ListenerHandle](https://github.com/nipafx/LibFX/wiki/ListenerHandle)**:
26 | Encapsulating an observable and a listener for easier add/remove of the listener ([I blogged about it here](java-listenerhandles)).
27 |
28 | **[Nestings](https://github.com/nipafx/LibFX/wiki/Nestings)**:
29 | Using all the power of JavaFX' properties for nested object aggregations.
30 |
31 | **[SerializableOptional](https://github.com/nipafx/LibFX/wiki/SerializableOptional)**:
32 | Serializable wrapper for `Optional`.
33 |
34 | **[WebViewHyperlinkListener](https://github.com/nipafx/LibFX/wiki/WebViewHyperlinkListener)**:
35 | Add hyperlink listeners to JavaFX' `WebView`.
36 |
37 | ## Getting Started
38 |
39 | The links above point to the [**LibFX** wiki on GitHub](https://github.com/nipafx/LibFX/wiki).
40 | It has an article for each feature explaining the concept, giving some examples and pointing to the best resource in the code to get started.
41 |
42 | Most key features also have self-contained demos, which can be found in [their own source folder](https://github.com/nipafx/LibFX/tree/master/src/demo/java/org/codefx/libfx).
43 |
44 | Finally, there's extensive Javadoc under [libfx.codefx.org/apidocs/](http://libfx.codefx.org/apidocs/).
45 |
46 | ## Getting LibFX 0.3.0
47 |
48 | You can download the jars from the [GitHub release site](https://github.com/nipafx/LibFX/releases/tag/v0.3.0) or use your favorite dependency management system:
49 |
50 |
51 |
52 | ```xml
53 |
54 | org.codefx.libfx
55 | LibFX
56 | 0.3.0
57 |
58 | ```
59 |
60 | ```groovy
61 | compile 'org.codefx.libfx:LibFX:0.3.0'
62 | ```
63 |
64 | **LibFX** is licensed under GLP 3.0 but other arrangements can be made - just ping me wherever you find me.
65 |
--------------------------------------------------------------------------------
/content/articles/2015-07-06-casting-in-java-8-and-beyond.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: "Casting In Java 8 (And Beyond?)"
3 | tags: [java-8, optional, streams]
4 | date: 2015-07-06
5 | slug: casting-in-java-8-and-beyond
6 | description: "Proposal to implement new casting methods on Java's `Class`. They aim to fulfill the need for improved ways to cast which was created by Java 8."
7 | intro: "Proposal to implement new casting methods on Java's `Class`. They aim to fulfill the need for improved ways to cast which was created by Java 8's `Optional` and `Stream`."
8 | searchKeywords: "cast"
9 | featuredImage: casting-java-8-and-beyond
10 | ---
11 |
12 | Casting an instance to a type reeks of bad design.
13 | Still, there are situations where there is no other choice.
14 | The ability to do this has hence been part of Java since day one.
15 |
16 | I think Java 8 created a need to slightly improve this ancient technique.
17 |
18 | ## Static Casting
19 |
20 | The most common way to cast in Java is as follows:
21 |
22 | ```java
23 | Object obj; // may be an integer
24 | if (obj instanceof Integer) {
25 | Integer objAsInt = (Integer) obj;
26 | // do something with 'objAsInt'
27 | }
28 | ```
29 |
30 | This uses the `instanceof` and cast operators, which are baked into the language.
31 | The type to which the instance is cast, in this case `Integer`, must be statically known at compile time, so let's call this static casting.
32 |
33 | If `obj` is no `Integer`, the above test would fail.
34 | If we try to cast it anyways, we'd get a `ClassCastException`.
35 | If `obj` is `null`, it fails the `instanceof` test but could be cast because `null` can be a reference of any type.
36 |
37 | ## Dynamic Casting
38 |
39 | A technique I encounter less often uses the methods on `Class` that correspond to the operators:
40 |
41 | ```java
42 | Object obj; // may be an integer
43 | if (Integer.class.isInstance(obj)) {
44 | Integer objAsInt = Integer.class.cast(obj);
45 | // do something with 'objAsInt'
46 | }
47 | ```
48 |
49 | Note that while in this example the class to cast to is also known at compile time, this is not necessarily so:
50 |
51 | ```java
52 | Object obj; // may be an integer
53 | Class type = // may be Integer.class
54 | if (type.isInstance(obj)) {
55 | T objAsType = type.cast(obj);
56 | // do something with 'objAsType'
57 | }
58 | ```
59 |
60 | Because the type is unknown at compile type, we'll call this dynamic casting.
61 |
62 | The outcomes of tests and casts for instances of the wrong type and null references are exactly as for static casting.
63 |
64 | ## Casting In Streams And Optionals
65 |
66 | ### The Present
67 |
68 | Casting the value of an `Optional` or the elements of a `Stream` is a two-step-process: First we have to filter out instances of the wrong type, then we can cast to the desired one.
69 |
70 | With the methods on `Class`, we do this with method references.
71 | Using the example of `Optional`:
72 |
73 | ```java
74 | Optional> obj; // may contain an Integer
75 | Optional objAsInt = obj
76 | .filter(Integer.class::isInstance)
77 | .map(Integer.class::cast);
78 | ```
79 |
80 | That we need two steps to do this is no big deal but I feel like it is somewhat awkward and more verbose than necessary.
81 |
82 | ### The Future (Maybe)
83 |
84 | I propose to implement casting methods on `Class` which return an `Optional` or a `Stream`.
85 | If the passed instance is of the correct type, an `Optional` or a singleton `Stream` containing the cast instance would be returned.
86 | Otherwise both would be empty.
87 |
88 | Implementing these methods is trivial:
89 |
90 | ```java
91 | public Optional castIntoOptional(Object obj) {
92 | if (isInstance(obj))
93 | return Optional.of((T) obj);
94 | else
95 | Optional.empty();
96 | }
97 |
98 | public Stream castIntoStream(Object obj) {
99 | if (isInstance(obj))
100 | return Stream.of((T) obj);
101 | else
102 | Stream.empty();
103 | }
104 | ```
105 |
106 | This lets us use `flatMap` to filter and cast in one step:
107 |
108 | ```java
109 | Stream> stream; // may contain integers
110 | Stream streamOfInts = stream.
111 | flatMap(Integer.class::castIntoStream);
112 | ```
113 |
114 | Instances of the wrong type or null references would fail the instance test and would lead to an empty `Optional` or `Stream`.
115 | There would never be a `ClassCastException`.
116 |
117 | ### Costs And Benefits
118 |
119 | What is left to be determined is whether these methods would pull their own weight:
120 |
121 | - How much code could actually use them?
122 | - Will they improve readability for the average developer?
123 | - Is saving one line worth it?
124 | - What are the costs to implement and maintain them?
125 |
126 | I'd answer these questions with *not much*, *a little*, *yes*, *low*.
127 | So it's close to a zero-sum game but I am convinced that there is a small but non-negligible benefit.
128 |
129 | What do you think?
130 | Do you see yourself using these methods?
131 |
--------------------------------------------------------------------------------
/content/articles/2015-08-04-all-about-project-jigsaw-on-infoq.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: "All About Project Jigsaw On InfoQ"
3 | tags: [java-next, java-9, project-jigsaw]
4 | date: 2015-08-04
5 | slug: project-jigsaw-on-infoq
6 | description: "My posts about Project Jigsaw got polished and published on InfoQ."
7 | searchKeywords: ""
8 | featuredImage: project-jigsaw-on-infoq
9 | ---
10 |
11 | Over the last few weeks I had the opportunity to polish [my posts about Project Jigsaw](tag:project-jigsaw) for InfoQ.
12 | The result was published today:
13 |
14 | **[Project Jigsaw is Really Coming in Java 9](http://www.infoq.com/articles/Project-Jigsaw-Coming-in-Java-9)**
15 |
16 | Besides refining what I wrote about [motivation, goals](motivation-goals-project-jigsaw), [the core concept, features](features-project-jigsaw) and [risks](how-java-9-and-project-jigsaw-may-break-your-code) it casts light on the history and current structure, and presents the strawman syntax from [JEP 200](http://openjdk.java.net/jeps/200).
17 | If you haven't read much about Jigsaw, this is your chance to get a comprehensive view of it.
18 |
19 | And thanks to [Victor Grazi](http://www.infoq.com/author/Victor-Grazi) for his excellent editing and perseverance.
20 | It improved and tightened the text noticeably.
21 |
22 | ## Next Steps
23 |
24 | Working on the article took a lot of time.
25 | (Which is why I count this lousy announcement here as one of the three posts I want to publish each month.) But now that I am done with that the road is clear to experimenting with the module system itself!
26 |
27 | This be possible as soon as the current work on [JSR 376](https://www.jcp.org/en/jsr/detail?id=376) is merged into the OpenJDK repositories, which can happen [any day now](http://mail.openjdk.java.net/pipermail/jigsaw-dev/2015-July/004393.html).
28 |
29 | Stay tuned.
30 |
--------------------------------------------------------------------------------
/content/articles/2015-08-14-interview-about-comments-on-dzone.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: "Interview About Comments On DZone"
3 | tags: [clean-comments, documentation]
4 | date: 2015-08-14
5 | slug: interview-about-comments-on-dzone
6 | description: "Matt Werner from DZone interviewed me about my stance on comments."
7 | searchKeywords: ""
8 | featuredImage: comment-your-fucking-code
9 | ---
10 |
11 | Forgetful me.
12 | About three weeks ago [Matt Werner from DZone](https://dzone.com/users/1057629/mwerner.html) gave me a chance to ramble about [my rant on commenting your fucking code](comment-your-fucking-code).
13 | We did this in form of a Q&A, which went up on DZone last week.
14 | Here you go:
15 |
16 | **[You Should Still Comment Your Code](https://dzone.com/articles/you-should-still-comment-your-code-a-qa-with-nicol)**
17 |
18 | Luckily I was given the chance to smooth out the rough parts, so it reads better than I sound.
19 |
20 | ## Why Even Talk About Comments?
21 |
22 | If you've read my [rant](comment-your-fucking-code) and my following [thoughts on comments](thoughts-on-comments), you know that my perspective is at odds with what many people think about comments in clean code.
23 | But there are also many people which share my distrust towards the "comments are a failure" position, that was mainly inspired by Uncle Bob's Clean Code.
24 |
25 | So yes, I see reasons to continue talking about comments.
26 | Over the next couple of posts (about this topic; don't fret, there will be others) I will try to carve out a position that reconciles my tendency to overdocument with the utter lack of helpful documentation I see on a daily basis.
27 |
--------------------------------------------------------------------------------
/content/articles/2015-11-09-javaone-2015-introduction-to-modular-development.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: "JavaOne 2015: Introduction to Modular Development"
3 | tags: [java-next, impulse, java-9, community, project-jigsaw]
4 | date: 2015-11-09
5 | slug: javaone-2015-introduction-to-modular-development
6 | description: "JavaOne 2015 saw a series of talks by the Project Jigsaw team about modularity in Java 9. This one introduces the basic concepts."
7 | searchKeywords: "JavaOne"
8 | featuredImage: javaone-project-jigsaw-introduction-sf
9 | ---
10 |
11 |
12 |
13 | After [preparing for JDK 9](javaone-2015-prepare-for-jdk-9) let's continue with an introduction to modular development!
14 |
15 | - **Content**: Introduction to the module system and the concept of modules
16 | - **Speaker**: Alan Bateman
17 | - **Links**: [Video](https://www.youtube.com/watch?v=8RhwmJlZQgs&t=4h25m19s) and [Slides](http://openjdk.java.net/projects/jigsaw/j1/intro-modular-dev-j1-2015.pdf)
18 |
19 |
20 |
21 | ## What Is A Module?
22 |
23 | [PLAY](https://www.youtube.com/watch?v=8RhwmJlZQgs#t=4h26m38s)
24 | Alan Bateman starts by explaining the basic concept of modules as named, self describing collections of code and data.
25 | This part is more than covered by [The State Of The Module System](http://openjdk.java.net/projects/jigsaw/spec/sotms/) (SOTMS):
26 |
27 | - [Modules](http://openjdk.java.net/projects/jigsaw/spec/sotms/#modules) and [module declarations](http://openjdk.java.net/projects/jigsaw/spec/sotms/#module-declarations)
28 | - [Module graphs](http://openjdk.java.net/projects/jigsaw/spec/sotms/#module-graphs)
29 | - [Readability](http://openjdk.java.net/projects/jigsaw/spec/sotms/#readability) and [implied readability](http://openjdk.java.net/projects/jigsaw/spec/sotms/#implied-readability)
30 | - [Accessibility](http://openjdk.java.net/projects/jigsaw/spec/sotms/#accessibility)
31 |
32 | ## Platform Modules
33 |
34 | [PLAY](https://www.youtube.com/watch?v=8RhwmJlZQgs#t=4h39m58s)
35 | Platform modules are the ones that make up the JDK - [SOTMS explains them](http://openjdk.java.net/projects/jigsaw/spec/sotms/#platform-modules) as well.
36 | Their dependency graph is shown on [Slide 19](http://openjdk.java.net/projects/jigsaw/j1/intro-modular-dev-j1-2015.pdf#page=19):
37 |
38 |
39 |
40 | A [very similar graph](https://bugs.openjdk.java.net/secure/attachment/21573/jdk-tr.png) that includes the OpenJDK-specific modules can be found in [JEP 200](http://openjdk.java.net/jeps/200).
41 |
42 | Bateman also mentions `java -listmods`, which will list all the available platform modules.
43 | (Note that there are [discussions on the mailing list](http://mail.openjdk.java.net/pipermail/jigsaw-dev/2015-October/005042.html) to rename the flag.)
44 |
45 | ## Command Line
46 |
47 | [PLAY](https://www.youtube.com/watch?v=8RhwmJlZQgs#t=4h42m39s)
48 | After explaining the [module path](http://openjdk.java.net/projects/jigsaw/spec/sotms/#module-path) Bateman gives an introduction to the various new command line options.
49 | The [Jigsaw quick-start guide](http://openjdk.java.net/projects/jigsaw/quick-start) has us covered here.
50 |
51 | An option the guide does not mention is `java -Xdiag:resolver`, which outputs additional information regarding module dependency resolution.
52 |
53 | ## Packaging As Modular JAR
54 |
55 | [PLAY](https://www.youtube.com/watch?v=8RhwmJlZQgs#t=4h49m54s)
56 | Modules can be packaged into so called modular JARs, which the [quick-start guide](http://openjdk.java.net/projects/jigsaw/quick-start#packaging) covers as well.
57 |
58 | Bateman stresses that such JARs work both on the module path in Java 9 as well as on the class path in Java 8 (as long as they target 1.8).
59 | He also quickly shows how the module path and class path can be mixed to launch a program.
60 |
61 | ## Linking
62 |
63 | [PLAY](https://www.youtube.com/watch?v=8RhwmJlZQgs#t=4h56m13s)
64 | Linking allows to bundle some modules and all of their transitive dependencies into a run-time image.
65 | If the initial modules are platform modules, the result will essentially be a variant of the JDK.
66 | This is in fact how the current Jigsaw builds are being created.
67 |
68 | This is done with the new tool *jlink* and the [quick-start guide](http://openjdk.java.net/projects/jigsaw/quick-start#linker) shows how to do it.
69 |
70 | ## Questions
71 |
72 | There were a couple of interesting questions.
73 |
74 | ### Is There Any Solution For Optional Dependencies?
75 |
76 | [PLAY](https://www.youtube.com/watch?v=8RhwmJlZQgs#t=5h04m43s)
77 | In earlier Jigsaw prototypes there was a notion of *optional dependencies*.
78 | Working out the precise semantics turned out to be hard so the feature was not implemented.
79 | Research showed that optional dependencies can typically be refactored to services that might or might not be present at runtime.
80 |
81 | Services are covered by the [quick-start guide](http://openjdk.java.net/projects/jigsaw/quick-start#services).
82 |
83 | ### Can jlink Cross-Compile?
84 | Can It Create A Self-Executing File?
85 |
86 | [PLAY](https://www.youtube.com/watch?v=8RhwmJlZQgs#t=5h05m39s)
87 | "Yes" and "Not directly but other tools will be improved so that will be doable in the future".
88 |
89 | ### Can Modules Be Versioned?
90 |
91 | [PLAY](https://www.youtube.com/watch?v=8RhwmJlZQgs#t=5h07m42s)
92 | Long story short: "Versions are hard, we don't want to replicate build tool functionality, so 'No'".
93 | For more, listen to Mark Reinhold's full answer.
94 |
95 | ### Can jlink Use Cross-Module Optimizations?
96 |
97 | [PLAY](https://www.youtube.com/watch?v=8RhwmJlZQgs#t=5h10m22s)
98 | Yes.
99 |
100 | ### How Does JavaDoc Handle Modules?
101 |
102 | [PLAY](https://www.youtube.com/watch?v=8RhwmJlZQgs#t=5h14m37s)
103 | JavaDoc will be upgraded so that it understands what modules are.
104 | It will display them along with packages and classes.
105 | And it will also by default not generate documentation for types in not-exported packages.
106 |
--------------------------------------------------------------------------------
/content/articles/2015-12-02-delay-of-java-9-release.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: "Six-Month Delay Of Java 9 Release"
3 | tags: [java-next, java-9, project-jigsaw]
4 | date: 2015-12-02
5 | slug: delay-of-java-9-release
6 | description: "Mark Reinhold proposed a six-month delay of JSR 376 / Project Jigsaw and thus of the Java 9 release. According to this JDK 9 would come out in March 2017."
7 | searchKeywords: "Java 9 Release"
8 | featuredImage: delay-of-Java-9-release-proposed
9 | ---
10 |
11 | Yesterday evening Mark Reinhold, Chief Architect of the Java Platform Group at Oracle and Specification Lead of [JSR 376](https://www.jcp.org/en/jsr/detail?id=376), for which Project Jigsaw is the current prototype, proposed a six-month extension of the schedules [for the JSR](http://mail.openjdk.java.net/pipermail/jpms-spec-observers/2015-December/000233.html) and [for Java 9](http://mail.openjdk.java.net/pipermail/jdk9-dev/2015-December/003149.html) release.
12 |
13 | ## Proposal
14 |
15 | The interleaved schedule proposals for modularity and Java 9 look as follows:
16 |
17 | - **2016-01** — JSR 376: Early Draft Review
18 | - **2016-05** — JDK 9: Feature Complete
19 | - **2016-06** — JSR 376: Public Review
20 | - **2016-08** — JDK 9: Rampdown Start
21 | - **2016-10** — JDK 9: Zero Bug Bounce
22 | - **2016-12** — JSR 376: Proposed Final Draft
23 | - **2016-12** — JDK 9: Rampdown Phase 2
24 | - **2017-01** — JDK 9: Final Release Candidate
25 | - **2017-03** — JSR 376: Final Release
26 | - **2017-03** — JDK 9: General Availability
27 |
28 | The definition for the JDK 9 milestones are [the same as for JDK 8](http://openjdk.java.net/projects/jdk8/milestones#definitions) and worth a read.
29 | Especially feature complete, which means that "\[a\]ll features have been implemented and integrated into the master forest, together with unit tests." It does not mean that development stops.
30 | Instead reckless improvements are still possible, at least until rampdown phases start, in which "increasing levels of scrutiny are applied to incoming changes."
31 |
32 | The proposals are up for debate until December 8th but I'd be very surprised to not see them become the new schedule.
33 |
34 | ## Reason
35 |
36 | The reasons for this delay clearly are JSR 376 and Jigsaw:
37 |
38 | > In the current JDK 9 schedule [\[7\]](http://openjdk.java.net/projects/jdk9/) the Feature Complete milestone is set for 10 December, less than two weeks from today, but Jigsaw needs more time.
39 | The JSR 376 EG has not yet published an Early Draft Review specification, the volume of interest and the high quality of the feedback received over the last two months suggests that there will be much more to come, and we want to ensure that the maintainers of the essential build tools and IDEs have adequate time to design and implement good support for modular development.
40 | >
41 | > [Mark Reinhold - 1 Dec 2015](http://mail.openjdk.java.net/pipermail/jdk9-dev/2015-December/003149.html)
42 |
43 | This makes a lot of sense.
44 | And while I think highly of the current prototype there is still lots of work to do.
45 | The additional six months will give the engineers more time to address the various problems and improve migration compatibility.
46 |
47 | > As with previous schedule changes, the intent here is not to open the gates to a flood of new features unrelated to Jigsaw, nor to permit the scope of existing features to grow without bound.
48 | It would be best to use the additional time to stabilize, polish, and fine-tune the features that we already have rather than add a bunch of new ones.
49 | The later FC milestone does apply to all features, however, so reasonable proposals to target additional JEPs to JDK 9 will be considered so long as they do not add undue risk to the overall release.
50 | >
51 | > [Mark Reinhold - 1 Dec 2015](http://mail.openjdk.java.net/pipermail/jdk9-dev/2015-December/003149.html)
52 |
53 | The additional time might help in convincing some of the more critical members of the community.
54 | As it currently stands there are even members of the JSR 376 expert group which are openly opposing the path Jigsaw took.
55 | The common counter proposal is solely based on class loaders as used by, e.g., OSGi implementations.
56 |
--------------------------------------------------------------------------------
/content/articles/2016-03-07-atom-on-gentoo.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: "Building Atom On Gentoo"
3 | tags: [tools]
4 | date: 2016-03-07
5 | slug: atom-on-gentoo
6 | description: "See how to build Atom on Gentoo straight from the sources."
7 | intro: "While not particularly hard, building Atom on Gentoo is a little elusive and poorly documented. Look here for enlightenment!"
8 | searchKeywords: "atom on gentoo"
9 | featuredImage: atom-on-gentoo
10 | ---
11 |
12 | I've been very happy with my [switch to Gentoo](hello-2016#linux).
13 | One of the cool things is that I can use the package manager for most development tools as [Portage](https://wiki.gentoo.org/wiki/Portage) contains up-to-date versions of most of them.
14 | (Case in point, I just updated Node.js to a version that was released just four days ago.) All the more shocked was I when I found out that [Atom](https://atom.io/) isn't one of them and that information on how to install Atom on Gentoo is elusive.
15 |
16 | Maybe because in the end the process isn't that complicated.
17 | Basically I just had to build from source, mostly following the [documentation on how to do that](https://github.com/atom/atom/blob/master/docs/build-instructions/linux.md#linux).
18 | I'll still repeat it here to have it readily available when I have to update.
19 |
20 | ## Building Atom
21 |
22 | These steps worked for [Atom 1.5.3](https://github.com/atom/atom/releases/tag/v1.5.3).
23 |
24 | ### Requirements
25 |
26 | The first three requirements listed in the [documentation](https://github.com/atom/atom/blob/master/docs/build-instructions/linux.md#linux) are a 32/64 bit OS, the C++ tool chain and Git.
27 | Every Gentoo install covers that.
28 |
29 | Then come [Node.js](http://nodejs.org/download/) and its package manager [npm](https://www.npmjs.com/), which comes bundled with it.
30 | I [unmasked](https://wiki.gentoo.org/wiki/Knowledge_Base:Unmasking_a_package) all 5.x releases of Node (with `=net-libs/nodejs-5*`) but you should get a sufficiently new version even if you don't do that - make sure to check, though.
31 |
32 | Next on the list are the development headers for the [GNOME keyring](https://wiki.gnome.org/Projects/GnomeKeyring), which is the only non-obvious (and generally somewhat peculiar) step.
33 | Emerging `gnome-base/libgnome-keyring-3.12.0` fixed this for me.
34 |
35 | ### Build & Install
36 |
37 | These are just the [install instructions](https://github.com/atom/atom/blob/master/docs/build-instructions/linux.md#instructions):
38 |
39 | ```shell
40 | git clone https://github.com/atom/atom
41 | cd atom
42 | git checkout v1.5.3
43 | script/build
44 | sudo script/grunt install
45 | ```
46 |
47 | Have fun!
48 |
49 |
50 |
51 | ## Alternatives
52 |
53 | For an install that is better integrated with the OS you might want to use a real [ebuild](https://devmanual.gentoo.org/quickstart/).
54 |
55 | There are a couple of [Portage overlays containing Atom](https://gpo.zugaina.org/app-editors/atom), most noteworthy the ones belonging to the Gentoo-based distributions [Sabayon](https://en.wikipedia.org/wiki/Sabayon_Linux) and [Funtoo](https://en.wikipedia.org/wiki/Funtoo_Linux) but also others.
56 | I opted against this solution because using the overlay of another distribution looks like a troublesome move to a novice and using "some guy's overlay" doesn't sit well with my general paranoia.
57 |
58 | But you can also do it yourself - or so [Till claims](atom-on-gentoo) in the comments.
59 | If I find some time I'll try it and update this post.
60 |
--------------------------------------------------------------------------------
/content/articles/2016-07-25-oh-no-forgot-streamiterate.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: "Oh No, I Forgot `Stream::iterate`!"
3 | tags: [java-9, streams]
4 | date: 2016-07-25
5 | slug: java-9-stream-iterate
6 | description: "In Java 9 `Stream` gets a couple of new methods - one of them is an overload of `iterate` that takes a predicate and returns a finite stream."
7 | intro: "There I go babbling about new stream methods and then I forget one: a `Stream::iterate` overload that produces a finite stream."
8 | searchKeywords: "stream iterate"
9 | featuredImage: java-9-stream
10 | ---
11 |
12 | There I go talking about the new things that [Java 9 will bring to the stream API](java-9-stream) and then I forget one: a new overload for `iterate`.
13 | [D'oh!](https://www.youtube.com/watch?v=cnaeIAEp2pU) I updated that post but to make sure you don't miss it, I also put it into this one.
14 |
15 | ## `Stream::iterate`
16 |
17 | `Stream` already has a method `iterate`.
18 | It's a static factory method that takes a seed element of type `T` and a function from `T` to `T`.
19 | Together they are used to create a `Stream` by starting with the seed element and iteratively applying the function to get the next element:
20 |
21 | ```java
22 | Stream.iterate(1, i -> i + 1)
23 | .forEach(System.out::println);
24 | // output: 1 2 3 4 5 ...
25 | ```
26 |
27 | Great!
28 | But how can you make it stop?
29 | Well, you can't, the stream is infinite.
30 |
31 | Or rather you *couldn't* because this is where the new overload comes in.
32 | It has an extra argument in the middle: a predicate that is used to assess each element before it is put into the stream.
33 | As soon as the first elements fails the test, the stream ends:
34 |
35 | ```java
36 | Stream.iterate(1, i -> i <= 3, i -> i + 1)
37 | .forEach(System.out::println);
38 | // output: 1 2 3
39 | ```
40 |
41 | As it is used above, it looks more like a traditional for loop than the more succinct but somewhat alien `IntStream.rangeClosed(1, 3)` (which I still prefer but YMMV).
42 | It can also come in handy to turn "iterator-like" data structures into streams, like the ancient `Enumeration`:
43 |
44 | ```java
45 | Enumeration en = // ...
46 | if (en.hasMoreElements()) {
47 | Stream.iterate(
48 | en.nextElement(),
49 | el -> en.hasMoreElements(),
50 | el -> en.nextElement())
51 | .forEach(System.out::println);
52 | }
53 | ```
54 |
55 | You could also use it to manipulate a data structure while you stream over it, like [popping elements off a stack](http://stackoverflow.com/q/38159906/2525313).
56 | This not generally advisable, though, because the source may end up in a surprising state - you might want to discard it afterwards.
57 |
58 |
59 |
60 | Not True!
61 | Turns out neither the `Enumeration` above nor the `Stack` mentioned in the link can be streamed like this - at least not fully.
62 | The predicate (in our cases `el -> en.nextElement()` and `el -> stack.pop()`) is evaluated *after* an element was taken from the source.
63 | This is in line with how the traditional `for`-loop works but has an unfortunate effect.
64 |
65 | After taking the last element from the source but before pushing it into the stream, the predicate is consulted and returns false because there is no element *after* the last one.
66 | The element does hence not appear in the stream, which means the last element is always missing.
67 |
68 | Thanks to Piotr for pointing this out!
69 |
70 |
71 |
--------------------------------------------------------------------------------
/content/articles/2016-08-04-goodbye-disy-hello-sitepoint.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: "Goodbye Disy, Hello SitePoint"
3 | tags: [meta, personal]
4 | date: 2016-08-04
5 | slug: goodbye-disy-hello-sitepoint
6 | description: "I worked for Disy for about 2 years. Now I said goodbye to become the editor of SitePoint's burgeoning Java channel and have more time for other projects."
7 | featuredImage: goodbye-disy-hello-sitepoint
8 | ---
9 |
10 | I've been working for [Disy](http://www.disy.net/en/home.html) for about 2 years.
11 | During that time my side projects [have grown and grown](codefx-levels-up) and taken up ever more of my free time.
12 | When [SitePoint](http://sitepoint.com/) offered me a part-time position as an editor, I did a 180 - now I have a couple of projects and a side job.
13 |
14 | ## Goodbye Disy
15 |
16 | Working at Disy was a lot of fun!
17 | The technical day to day work never quite got me but we had a lot of very interesting meta-problems to solve.
18 |
19 | [A monolith](http://www.disy.net/en/products/cadenza.html) with about 1.5 million lines of code split across \~400 Maven modules poses challenges that you won't learn to solve from coding up a [to-do-list-app](https://medium.com/@filiph/the-hello-world-fallacy-ef4f43ca8b7e#.pvppu1rv0) in the freshest fad.
20 | Fast(ish) reliable builds, dependency management, shared code ownership, code quality, tool independence - all of these and more are much harder to achieve when you're not just a handful of devs hacking together a web app in twelve months.
21 |
22 | (I know, I know, "Why don't you just build microservices?" Has anyone even tried that with a Swing app?
23 | No?
24 | Hmm, I wonder why...)
25 |
26 | More than anything else I learned to be conservative when it comes to libraries, frameworks, tools, patterns, everything really.
27 | Even a little cynical maybe - seeing so many of them fall to pieces when used on a large code base made me wonder whether they were even meant to be used for real-world projects.
28 | I consider this experience an extremely valuable one to have made.
29 |
30 | And then there were the people and, by extension, the company, which were plain awesome!
31 | No longer working with them everyday was the hardest part of saying goodbye to Disy.
32 |
33 | Guys and gals, I will miss you!
34 |
35 | ## Hello SitePoint
36 |
37 | SitePoint is building a Java channel and asked me to become its editor.
38 | Oh, the pride!
39 | And it's right up my alley, too!
40 | I've built three blogs (this one, [Do-Foss](http://blog.do-foss.de/en/), and [Disy's TechBlog](https://blog.disy.net/)) and feel right at home in the Java community, This offer gave me an opportunity to build on this and make it a more integral part of my life.
41 |
42 | So since Monday I've been doing my new thing: finding authors, curating content, and generally scheming to make the channel a great success.
43 |
44 | "So where is it?" you might ask and my answer would be "Not quite there yet." I will tentatively point you towards [the Java tag](https://www.sitepoint.com/tag/java-2/) but with two caveats:
45 |
46 | - We're still building valuable content.
47 | - Don't bookmark anything yet, another URL might supersede this one.
48 |
49 | If you don't want to miss the big unveiling, follow me.
50 |
51 | ## What Else?
52 |
53 | So what are the other projects I was talking about?
54 |
55 | ### Java Module System in Action
56 |
57 | Yes, it's still on...
58 | I woefully neglected working on it but with more free time now, I made it my top priority after SitePoint.
59 |
60 | ### CodeFX
61 |
62 | I will of course continue to write here.
63 | I can't wait to bore you with more details about [JUnit 5](tag:junit-5), [Java 9](tag:java-9)/[Project Jigsaw](tag:project-jigsaw), or [Clean Comments](tag:clean-comments).
64 | Heck, I might even write about something else one day.
65 |
66 | That's actually one thing I planned.
67 | My list of ideas contains a lot of topics that are not immediately technical but address development as a whole.
68 | I've always been interested in the cultural and social aspects of creating software and can't wait to share my thoughts.
69 | On Disy's blog I already started to write about [how we/they do code reviews](https://blog.disy.net/code-reviews/) - a series, which I will soon cross-post here.
70 |
71 | ### Bla, Bla, Bla
72 |
73 | Yes, I do talks:
74 |
75 | - [past talks](past-talks)
76 | - [upcoming talks](schedule)
77 |
78 | (If you know me, you're now thinking "Of course you are... *roll-eyes*".)
79 |
80 | ### For Hire
81 |
82 | Turns out that knowledge about Java 9 and JUnit 5 interests other people as well (who would've thought?).
83 | If you or your company are of such a curious persuasion and would like to get some help on planning migrations or training you and your fellow developers, you can hire me for that - just [drop me a mail](mailto:nicolai@nipafx.dev).
84 |
85 | ### Err, coding?
86 |
87 | Ah, yes.
88 | Looks like I'm no longer a coder who writes - technically I'm now a writer/editor who ... codes?
89 | Do I?
90 | Well, it's a passion, so I'm sure it'll push its way through.
91 | In fact, just yesterday I started to work on [a new side project](https://github.com/CodeFX-org/WorkFlowyFX), which uses - take a deep breath - JavaScript.
92 | Shocker!
93 |
94 | But I have to make sure that I have time left to code.
95 | Otherwise I'll just end up an author writing about things he has no clue about.
96 | And I hate those!
97 |
--------------------------------------------------------------------------------
/content/articles/2016-09-05-ultimate-guide-java-9.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: "The Ultimate Guide To Java 9"
3 | tags: [java-next, java-9]
4 | date: 2016-09-05
5 | slug: ultimate-guide-java-9
6 | canonicalUrl: https://www.sitepoint.com/ultimate-guide-to-java-9/
7 | description: "Java 9 is coming! Besides Jigsaw it brings new language features and many new and improved APIs. Check out the ultimate guide."
8 | intro: "I'm sure you've heard this and that about Java 9: modularity, collection literals (or not?), private methods on interfaces, etc. But if you really want to know all that's coming, you need this ultimate guide."
9 | searchKeywords: ""
10 | featuredImage: ultimate-guide-to-java-9
11 | ---
12 |
13 | Today was the grand opening of [SitePoint's Java channel](http://sitepoint.com/java) and we kicked it off with [the ultimate guide to Java 9](https://www.sitepoint.com/ultimate-guide-to-java-9/).
14 | We left out Project Jigsaw because [so much has already been written about it](tag:project-jigsaw) and focused on everything else - and there's *a lot* of it!
15 |
16 | - Language Changes
17 | - Private Interface (Default) Methods
18 | - Try-With-Resources on Effectively Final Variables
19 | - Diamond Operator for Anonymous Classes
20 | - SaveVarargs on Private Methods
21 | - No More Deprecation Warnings for Imports
22 | - APIs
23 | - OS Processes
24 | - Multi-Resolution Images
25 | - Stack Walking
26 | - Redirected Platform Logging
27 | - Reactive Streams
28 | - Collection Factory Methods
29 | - Native Desktop Integration
30 | - Deserialization Filter
31 | - Networking
32 | - HTTP/2
33 | - Datagram Transport Layer Security (DTLS)
34 | - TLS Application-Layer Protocol Negotiation Extension (TLS ALPN)
35 | - OCSP Stapling for TLS
36 | - XML
37 | - OASIS XML Catalogs Standard
38 | - Xerces 2.11.0
39 | - Extensions to Existing APIs, e.g.
40 | - [Optional](java-9-optional), [Stream](java-9-stream), and Collectors
41 | - DateTime API
42 | - Matcher
43 | - Atomic…
44 | - Array utilities
45 | - Low Level APIs
46 | - Variable Handles Aka VarHandles
47 | - Enhanced Method Handles
48 | - Dynalink
49 | - Nashorn Parser API
50 | - Spin-Wait Hints
51 | - Deprecations
52 | - Applet API
53 | - Corba
54 | - Observer, Observable
55 | - SHA-1
56 | - Removals
57 |
58 | Now, don't tell me, you're not curious!
59 | Go check it out:
60 |
61 | **[The Ultimate Guide to Java 9](https://www.sitepoint.com/ultimate-guide-to-java-9/)**
62 |
--------------------------------------------------------------------------------
/content/articles/2016-11-24-hello-world.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: "SPJCN I: Hello World"
3 | tags: [community]
4 | date: 2016-11-24
5 | slug: spjcn-hello-world
6 | canonicalText: "I originally wrote this for Sitepoint's Java newsletter, but this issue never got published online."
7 | description: "In the first issue of SitePoint's Java Channel Newsletter (September 9th 2016) I babble about community and conferences."
8 | featuredImage: spjcn-i-new-york
9 | ---
10 |
11 | Hello World, and welcome to our Java newsletter - not just any but the very first!
12 | Definitely a reason to celebrate so I'm having a beer.
13 | If you want to get yourself a drink as well, now would be a good time.
14 | I'll wait here and think about what to write next.
15 |
16 | ## Introductions
17 |
18 | Since we'll be spending some time together, why don't I start by introducing myself?
19 | My name's Nicolai and I'm your editor (don't tell SitePoint, they think I'm *their* editor).
20 | I'll be making sure that [the Java channel](https://sitepoint.com/java) is brimming with relevant content and will work hard to make it your go-to source for everything Java.
21 | On top of that, they'll let me out of my cage every two weeks to crank out one of these editorials.
22 |
23 | I've been coding Java on and off since 2001 and began doing it professionally in 2011.
24 | Being a know-it-all I started blogging in 2014, which led me to becoming a part-time author and eventually an editor.
25 | If you want to know more (and why wouldn't you?), you can find me at [nipafx.dev](https://nipafx.dev).
26 | To get in touch use [mail](mailto:nicolai.parlog@sitepoint.com), [Twitter](https://twitter.com/nipafx), or, if you absolutely have to, [Google+](https://google.com/+NicolaiParlog).
27 |
28 | ## So What Is This About?
29 |
30 | There are 9 million people out there using Java \[citation needed\].
31 | Frankly, thinking about that blows my mind.
32 | Imagine being in New York City, Cairo, or Bangkok and *everyone* is a Java developer!
33 |
34 | Wherever you go, whoever you talk to, everybody's having a screen right next to them, showing IntelliJ, Eclipse, or Netbeans.
35 | Red for failing tests, green for passing, white-on-black consoles trailing logs or watching Maven download the world.
36 | Jenkins serves freshly finished builds.
37 | In your office, on the streets, in the coffee shop, at parties - everybody's hacking away at some Java project.
38 |
39 | Are you wondering about how to manage exceptions in stream pipelines, whether SonarQube makes FindBugs obsolete, how to tune the garbage collector, or whether Java 9 will break your project?
40 | Imagine you could strike up a conversation with literally everybody you meet in this Java metropolis of ours.
41 |
42 | Now, unfortunately we're not all living in the same city.
43 | We're dispersed over all the continents and what holds us together are the conferences, mailing lists, private and company blogs, sites like SitePoint, newsletters, courses, and whatnot.
44 | They are constantly and chaotically moving Java along.
45 |
46 | But I know that you're busy - working, learning, living takes time and following what's going in the community comes on top.
47 | So here's my proposal: I will put my ear to the ground, curate and summarize what I hear, and report back to you every two weeks.
48 | Your task is to get in touch with me about anything you find interesting and of course to enjoy reading the newsletter.
49 | What do you think - do we have a deal?
50 |
51 | Ok, let's go then!
52 | I've been blabbering about community a lot so why not continue down that road?
53 |
54 | ## Conference Season
55 |
56 | After its seasonal break, the conference carousel is picking up again.
57 | During the next couple of months a lot of great meetings are taking place all over the world - just to name a few:
58 |
59 | - [JavaZone](https://javazone.no/), Oslo, last couple of days
60 | - [JAXLondon](https://jaxlondon.com/), London, October 10th to 12th
61 | - [GeeCON](http://www.geecon.org/), Pargue, October 20th and 21st
62 | - [Devoxx Morocco](https://www.devoxx.ma/), Casablanca, November 1st to 3rd
63 | - [Devoxx Belgium](https://www.devoxx.be/), Antwerpen, November 7th to 11th
64 | - [QCon](http://www.qconferences.com/) in Shanghai, San Francisco, and Tokyo
65 |
66 | But one overshadows them all: [JavaOne](https://www.oracle.com/javaone/index.html).
67 | From September 18th to 22nd thousands of Java-ists will meet in San Francisco to discuss everything Java.
68 | Don't you wish someone would pay for you and send you there?
69 | I sure do... but, alas, nobody does so we have to content ourselves with YouTube, where the talks will show up soon after they were held.
70 | I'll binge watch as many as I can and come back with a list of recommendations - including yours if you liked a particular talk and told me about it.
71 |
72 | In the meantime you could check out [our summary of the Java Virtual Machine Language Summit](https://www.sitepoint.com/jvmls-2016/), which took place in the first week of August in Santa Clara.
73 | A great panel of speakers discussed the future of Java and the JVM, mostly related to the projects Jigsaw (modularity), Valhalla (value types and generics over primitives), and Panama (going native).
74 | While targeting JVM aficionados there are a lot of takeaways for regular developers like you and me as well.
75 |
76 | ## Wrapping Things Up
77 |
78 | Let me leave you with a couple of articles I think you might find interesting:
79 |
80 | - [The Ultimate Guide to Java 9](https://www.sitepoint.com/ultimate-guide-to-java-9/)
81 | - [HTTP/2 Client in Java 9](https://getpocket.com/redirect?url=http%3A%2F%2Fblog.oio.de%2F2016%2F08%2F24%2Fhttp2-client-java-9%2F&formCheck=887e26de4268d0ee02dc2a1e9f0a9833)
82 | - [Java, Unicode, and the Mysterious Compile Error](https://www.sitepoint.com/java-unicode-mysterious-compile-error/)
83 | - [Using jOOλ to Combine Several Java 8 Collectors into One](https://blog.jooq.org/2016/08/29/using-joo%CE%BB-to-combine-several-java-8-collectors-into-one/)
84 |
85 | I wish you a great time!
86 |
87 | so long ... Nicolai
88 |
--------------------------------------------------------------------------------
/content/articles/2017-08-14-planning-your-java-9-update.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: "Planning Your Java 9 Update"
3 | tags: [java-9, jdeps, migration]
4 | date: 2017-08-14
5 | slug: planning-your-java-9-update
6 | description: "A Java 9 update is not always trivial; quite the opposite, migrating to Java 9 can be challenging. Here's how to gather and categorize problems."
7 | intro: "Time to put your Java 9 knowledge into practice and plan your applications migration. Here's how to get an overview of what needs to be done."
8 | searchKeywords: "Java 9 update"
9 | featuredImage: java-9-migration-planning
10 | ---
11 |
12 | You've read [the module system tutorial](java-module-system-tutorial) and [the Java 9 migration guide](java-9-migration-guide) and now you're ready to start your Java 9 update?
13 | Great!
14 | Here are some tips on how to get a sense of what's awaiting you.
15 |
16 | ## Looking For Trouble
17 |
18 | There are two obvious steps to take to gather the first data points for how challenging your update will be:
19 |
20 | - Run your regular build entirely on Java 9, ideally in a way that lets you gather all errors instead of stopping at the first.
21 | - If you're developing an application, build it as you do normally (meaning, not yet on Java 9) and then run it on Java 9.
22 | Consider using `--illegal-access=debug` or `deny` to get more information on illegal access.
23 |
24 | Carefully analyze the output, take note of new warnings and errors and try to link them to what you know about [migration challenges](java-9-migration-guide).
25 | Also look out for warnings or errors due to removed command line options.
26 |
27 | It is a good idea to apply some quick fixes like [adding exports](java-9-migration-guide#illegal-access-to-internal-apis) or [Java EE modules](java-9-migration-guide#dependencies-on-java-ee-modules).
28 | This allows you to see the tougher problems that may be hiding behind benign ones.
29 | In this phase, no fix is too dirty or too hacky - anything that gets the build to throw a new error is a victory.
30 | If you get too many compile errors, you could compile with Java 8 and just run the tests on Java 9.
31 |
32 | Then [run JDeps](jdeps-tutorial-analyze-java-project-dependencies) on your project *and your dependencies*.
33 | Analyze dependencies on [JDK-internal APIs](java-9-migration-guide#illegal-access-to-internal-apis) and take not of any [Java EE modules](java-9-migration-guide#dependencies-on-java-ee-modules).
34 | Also look for [split packages between platform modules and application JARs](java-9-migration-guide#split-packages).
35 | A good way to get started are the following two JDeps calls, where all your project's dependencies are in the `libs` folder:
36 |
37 | ```shell
38 | jdeps --jdk-internals -R --class-path 'libs/*' project.jar
39 | jdeps -s -R --class-path 'libs/*' project.jar
40 | ```
41 |
42 | Finally, search your code base for calls to `AccessibleObject::setAccessible`, [casts to `URLClassLoader`](java-9-migration-guide#casting-to-urlclassloader), [parsing of `java.version` system properties](java-9-migration-guide#new-version-strings), or [handcrafting resource URLs](java-9-migration-guide#rummaging-around-in-runtime-images).
43 | Put everything you found on one big list - now it's time to analyze it.
44 |
45 | ## How Bad Is It?
46 |
47 | The problems you've found should fall into the two categories "I've seen it in before" and "What the fuck is going on?".
48 | For the former, split it up further into "Has at least a temporary fix" and "Is a hard problem." Particularly hard problems are removed APIs and package splits between platform modules and JARs that do not implement an endorsed standard or a standalone technology.
49 |
50 | It's very important not to confuse prevalence with importance.
51 | You might get about a thousand errors because a Java EE module is missing, but fixing that is trivial.
52 | You're in big trouble, though, if your core feature depends on that one cast of the application class loader to `URLClassLoader`.
53 | Or you might have a critical dependency on a removed API but because you've designed your system well, it just causes a few compile errors in one subproject.
54 |
55 | A good approach is to ask yourself for each specific problem that you don't know a solution for off the top of your head: "How bad would it be if I cut out the troublesome code and everything that depends on it?" How much would that hurt your project?
56 |
57 | In that vein, would it be possible to temporarily deactivate the troublesome code?
58 | Tests can be ignored, features toggled with flags.
59 | Get a sense for the how feasible it is to delay a fix and run the build or the application without it.
60 |
61 | When you're all done you should have a list of issues in these three categories:
62 |
63 | - a known problem with an easy fix
64 | - a known, hard problem
65 | - an unknown problem, needs investigation
66 |
67 | For problems in the last two categories, you should know how dangerous they are for your project and how easy you could get by without fixing them right now.
68 |
69 | ## On Estimating Numbers
70 |
71 | Chances are, somebody wants you to make an estimate that involves some hard numbers - maybe in hours, maybe in cash.
72 | That's tough in general, but here it is particularly problematic.
73 |
74 | A [Java 9 migration](java-9-migration-guide) makes you face the music of decisions long past.
75 | Your project might be tightly coupled to an outdated version of that Web framework you wanted to update for years, or it might a have accrued a lot of technical debt around that unmaintained library.
76 | And unfortunately both stop working on Java 9.
77 | What you have to do now is pay back some technical debt and everybody knows that the fees and interest can be hard to estimate.
78 | Finally, just like a good boss battle, the critical problem, the one that costs you the most to fix, could very well be hidden behind a few other troublemakers, so you can't see it until you're in too deep.
79 |
80 | I'm not saying these scenarios are *likely* just that they're *possible*, so be careful with guessing how long it might take you to migrate to Java 9.
81 |
82 | ## Jumping Into Action
83 |
84 | The next step is to actually start working on the issues you collected.
85 | I recommend to not do that in isolation, but to set your build tool and continuous integration up to build your project with Java 9 and then start solving them one by one.
86 | More on that in another post.
87 |
--------------------------------------------------------------------------------
/content/articles/2017-12-31-goodbye-2017-hello-2018.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: "Goodbye 2017, Hello 2018"
3 | tags: [turn-of-the-year]
4 | date: 2017-12-31
5 | slug: goodbye-2017-hello-2018
6 | description: "2017 draws to a close and 2018 is knocking. My annual review and preview went to my newsletter, so subscribe or head over to Medium to read them."
7 | featuredImage: 2017-2018
8 | ---
9 |
10 | Every [turn of the year](tag:turn-of-the-year), I write a pair of posts: One looks back on my professional achievements and failures of the passing year, the other one defines goals for the next one.
11 | I used to publish these posts here on CodeFX:
12 |
13 | - [Goodbye 2014](goodbye-2014) and [Hello 2015](hello-2015)
14 | - [Goodbye 2015](goodbye-2015) and [Hello 2016](hello-2016)
15 | - [Goodbye 2016](goodbye-2016) and [Hello 2017](hello-2017)
16 |
17 | That was never a good fit, though, because this blog is supposed to contain only technical content.
18 | But this year, I have [an active newsletter](news) where such content fits in perfectly, so I use it for these two posts.
19 | If you don't feel like [subscribing](news), head over to Medium, [where I publish them a few days after](http://medium.com/codefx-weekly) (including [full RSS](https://medium.com/feed/codefx-weekly)).
20 |
21 | In fact, [Goodbye 2017 is already online](https://medium.com/codefx-weekly/goodbye-2017-14ecd2481cba), Hello 2018 will show up next week ([here you go](https://medium.com/codefx-weekly/hello-2018-f7a284abc1f1)).
22 |
23 | **I wish you a happy new year’s eve!
24 | I hope to see you again in 2018.**
25 |
--------------------------------------------------------------------------------
/content/talks/best-practices.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: "Best Practices Considered Harmful"
3 | tags: [techniques]
4 | date: 2019-06-03
5 | slug: talk-best-practices-harmful
6 | description: "A lightning talk about how best practices promote a one-size-fits all mentality that harms our ability to create solutions that are tailored to the problems at hand"
7 | searchKeywords: "best practices"
8 | featuredImage: best-practices
9 | slides: https://slides.nipafx.dev/best-practices
10 | ---
11 |
12 | Software development is full of "best practices" - index your database columns, write tests for your code, don't reinvent the wheel...
13 | But are these really "best"?
14 | Is it a good idea to blindly implement them?
15 | Shouldn't we discuss this?
16 |
17 | We absolutely should!
18 | This short talk dismantles the myth of "best practices", discarding a horrible name in order to redeem the underlying, often useful and proven solutions.
19 |
--------------------------------------------------------------------------------
/content/talks/comment-your-code.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: "Comment Your &*☠# Code!"
3 | tags: [agile, clean-comments, documentation]
4 | date: 2016-06-24
5 | slug: talk-comment-your-code
6 | description: "A heartfelt rant / thoughtful talk arguing for more comments in code"
7 | searchKeywords: "comments"
8 | featuredImage: comment-your-code
9 | slides: https://slides.nipafx.dev/comment-your-code
10 | videoSlug: comment-your-code-accento-2019
11 | ---
12 |
13 | You think your code is so clean that it doesn't need any comments?
14 | Or are your colleagues convinced that all comments are failures?
15 | Then this talk is for you!
16 |
17 | Let's first dispute some common arguments against commenting code:
18 |
19 | * Comments lie?
20 | * Tests are better?
21 | * Good names suffice?
22 |
23 | We find fault with all of them (and more)!
24 |
25 | With that out of the way we categorize comments and analyze their costs and benefits.
26 | This wills us the means to discuss the end:
27 | Which comments will improve a code base?
28 |
29 | Of course, every team has to come up with its own answer, but the vocabulary and ideas presented in this talk can help find it.
30 |
--------------------------------------------------------------------------------
/content/talks/expert-java-8.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: "Expert Java 8"
3 | tags: [java-8, lambda, streams, optional, default-methods]
4 | date: 2017-02-07
5 | slug: talk-expert-java-8
6 | description: "With this talk, I help you get the most out of lambdas, `Stream`s, `Optional`s, and default methods, helping you master Java 8's core features"
7 | searchKeywords: "java 8"
8 | featuredImage: java-8-expert
9 | slides: https://slides.nipafx.dev/expert-java-8
10 | videoSlug: expert-java-8-jfokus-2017
11 | ---
12 |
13 | By now Java 8's features are well understood, but some practical details are still unclear. Did you ever wonder...
14 |
15 | * how to create a "lambda-enabled" API?
16 | * whether your methods should return or even accept `Stream`s and how that might impact your design?
17 | * how to write readable `Stream` pipelines, especially when exceptions are involved?
18 | * about the details of and opinions on `Optional`?
19 | * how to use default methods to evolve interfaces without breaking client code?
20 |
21 | This talk discusses these and other advanced topics of Java 8, so you can get the most out of its awesome features.
22 |
--------------------------------------------------------------------------------
/content/talks/java-9-migration.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: "To JAR Hell And Back"
3 | # subtitle: A Live Migration to Java 11
4 | tags: [java-9, java-11, j_ms, migration]
5 | date: 2017-07-25
6 | slug: talk-java-9-migration
7 | description: "A live-coding talk where we take a typical Java 8 code base and update it to Java 9 and beyond, overcoming some common and some less common hurdles like dependencies on internal APIs and split packages"
8 | searchKeywords: "java 9 migration"
9 | featuredImage: java-9-migration
10 | slides: https://slides.nipafx.dev/java-9-migration
11 | videoSlug: java-9-migration-devoxx-be-2018
12 | repo: java-9-migration
13 | ---
14 |
15 | I'm sure you've heard about compatibility issues when upgrading from Java 8 to 9 and beyond, but did you try it yourself yet?
16 | This live coding session starts with a typical Java 8 application and runs up against and eventually overcomes the common hurdles:
17 |
18 | * build system configuration
19 | * dependency analysis with `jdeps`
20 | * dependencies on internal APIs and Java EE modules
21 | * split packages
22 |
23 | To get the most out of this talk, you should have a good understanding of the module system basics - afterwards you will know how to approach *your* application's migration to Java 9 and the module system.
24 |
--------------------------------------------------------------------------------
/content/talks/java-after-n.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: "Java After Eleven"
3 | tags: [java-11, java-12, java-13, java-14, java-15, java-16]
4 | date: 2020-02-05
5 | slug: talk-java-after-n
6 | description: "A live-coding talk during which I update a Java 11 code base to Java 16, making good use of new language features, additional and improved APIs, and JVM capabilities"
7 | featuredImage: java-after-n
8 | slides: https://slides.nipafx.dev/java-after-eight
9 | videoSlug: java-after-eight-jfokus-2020
10 | repo: java-after-eight
11 | ---
12 |
13 | Most projects that updated past Java 8 decided to stick to the LTS release 11.
14 | The new cadence created the illusion of not much happening after that, but nothing could be further from the truth - with new language features like switch expressions, text blocks, records, and sealed classes, Java is moving faster than ever.
15 |
16 | In this talk, we'll take a simple Java 11 code base, update it to 16, and refactor it to use the new language features and APIs.
17 | You'll be surprised how much the code changes!
18 |
--------------------------------------------------------------------------------
/content/talks/java-module-system.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: "The Java Module System Beyond The Basics"
3 | tags: [j_ms, migration]
4 | date: 2016-03-16
5 | slug: talk-java-module-system
6 | description: "In this talk, I go beyond the module system basics and present more advanced features for those who want to become their team's module system expert"
7 | searchKeywords: "java module system"
8 | featuredImage: java-module-system
9 | slides: https://slides.nipafx.dev/jpms
10 | videoSlug: jpms-java-saigon-2018
11 | repo: jpms-monitor
12 | ---
13 |
14 | Java 9 shipped the Java Platform Module System, which brings language-level modularity to the Java ecosystem.
15 | But you already know that and even spent some time to learn the basics?
16 | That's great because this talk takes you beyond that and shows how to...
17 |
18 | * model finer-grained dependencies and APIs
19 | * decouple modules with services
20 | * weigh encapsulation versus reflection
21 | * analyze dependencies with `jdeps`
22 | * safe the day with important command line flags
23 | * create runtime images with `jlink`
24 |
25 | With this under your belt, you're ready to become your team's module system expert.
26 |
--------------------------------------------------------------------------------
/content/talks/java-next.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: "Java Next"
3 | # subtitle: "New Releases, Amber, Valhalla, and More Goodies"
4 | tags: [java-next, project-amber, project-loom, project-valhalla]
5 | date: 2018-05-30
6 | slug: talk-java-next
7 | description: "In this talk we reflect over recent developments and peek into Java's future: the six-month release cycle, the new license and support landscape as well as recent and upcoming features"
8 | searchKeywords: "java update"
9 | featuredImage: java-next
10 | slides: https://slides.nipafx.dev/java-next
11 | videoSlug: java-next-vjug-2019
12 | ---
13 |
14 | With Java's switch to a six-month release schedule, the community needs to step up its game to stay up to date.
15 | Instead of having a year or more to prepare for a new release, it's a mere three months - we need to be better informed about what's going on to see changes coming before they're out.
16 |
17 | This talk:
18 |
19 | * explains the details behind the new schedule and how to stay up to date
20 | * discusses license and support of JVM distributions
21 | * showcases Java 9 to 15 language features like `var`, `switch` expressions, and records
22 | * shows the future of Java, brought by projects like Valhalla, Amber, and others
23 | * looks at features of upcoming releases like pattern matching, value types, and fibers
24 |
25 | Afterwards, you will not only know about the immediate future but also how to stay up to date without much effort.
26 |
--------------------------------------------------------------------------------
/content/talks/java-var.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: "Fun With `var`"
3 | tags: [anonymous-classes, default-methods, generics, lambda, java-10, var]
4 | date: 2018-11-08
5 | slug: talk-java-var
6 | description: "A live-coding talk where I show off all you need to know about `var` in Java. And then some."
7 | searchKeywords: "java var"
8 | featuredImage: java-var
9 | slides: https://slides.nipafx.dev/java-var
10 | videoSlug: java-var-jfall-2018
11 | repo: java-x-demo
12 | ---
13 |
14 | Since Java 10 you can use `var` to let the compiler infer a local variable's type:
15 |
16 | ```java
17 | var users = new ArrayList();
18 | ```
19 |
20 | And that's pretty much it, right?
21 | Surprisingly, no!
22 | There are a lot of details to consider...
23 |
24 | * is this JavaScript?!
25 | * how exactly is the type inferred?
26 | * where can I use `var` and what should I look out for?
27 | * won't this lead to unreadable code?
28 |
29 | ... and a few fun things to do with `var`...
30 |
31 | * playing with anonymous classes (don't!)
32 | * faking traits (don't!)
33 | * faking intersection types (do!)
34 |
35 | After this live-coding deep dive into `var`, you'll know all about Java 10's flagship feature.
36 |
--------------------------------------------------------------------------------
/content/talks/java-x.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: "Java 16 Is Coming!"
3 | tags: [java-9, java-10, java-11, java-12, java-13, java-14, java-15]
4 | date: 2017-02-23
5 | slug: talk-java-x
6 | description: "In this talk, I introduce the Java language features, new/updated APIs, and new JVM capabilities that recent Java releases brought to the ecosystem"
7 | searchKeywords: "java 15"
8 | featuredImage: java-16
9 | slides: https://slides.nipafx.dev/java-x
10 | repo: java-x-demo
11 | ---
12 |
13 | Many projects are still on Java 8, some already on 11 and yet, these days Java 16 gets released!
14 | Java's releases between 9 and 16 have a lot in stock - in this talk you'll learn about...
15 |
16 | * new language features like sealed types, records, switch expressions, `var`, and more
17 | * new APIs like stack walking and the reactive HTTP/2 client
18 | * the additions to existing APIs, like `Stream` and `Optional`
19 | * other niceties like multi-release JARs and performance improvements
20 |
21 | After this talk you will be prepared to get started with Java 16.
22 |
--------------------------------------------------------------------------------
/content/talks/junit-5.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: "JUnit 5"
3 | # subtitle: Next Generation Testing on the JVM
4 | tags: [junit-5, testing]
5 | date: 2016-05-20
6 | slug: talk-junit-5
7 | description: "In this talk, I introduce JUnit 5 from basic tests to more advanced features like nesting, parameterization, parallelization, and extensions. We also discuss its architecture and compatibility with JUnit 4."
8 | searchKeywords: "junit 5"
9 | featuredImage: junit-5
10 | slides: https://slides.nipafx.dev/junit-5
11 | # videoSlug: https://www.youtube.com/watch?v=OA3UJYxTBRA https://www.youtube.com/watch?v=VfC00bby8XQ
12 | repo: junit-5-demo
13 | ---
14 |
15 | Java's most ubiquitous library got an update! This talk...
16 |
17 | * shows you how to write tests with JUnit 5
18 | * walks you through the changes compared to JUnit 4
19 | * expands on nested, parameterized, parallel and other kinds of tests
20 | * tells you how to build your own JUnit 5 extensions
21 | * presents the new architecture
22 | * discusses compatibility with previous JUnit versions, IDEs, and other testing tools
23 |
24 | Be careful, though:
25 | You might end up with an urge to start using it right away.
26 |
--------------------------------------------------------------------------------
/content/talks/junit-pioneer.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: "To Jupiter And Beyond - On An Exploratory Mission With JUnit Pioneer"
3 | # subtitle:
4 | tags: [junit-5]
5 | date: 2021-03-18
6 | slug: talk-junit-pioneer
7 | description: "JUnit Pioneer gathers JUnit 5 extensions. This talk discusses the technical aspects, but also the mission, dev practices, automatic releases, and what Twitch has to do with all of this."
8 | searchKeywords: "junit 5 extensions"
9 | featuredImage: junit-pioneer-helmet
10 | slides: https://slides.nipafx.dev/junit-pioneer
11 | # videoSlug:
12 | ---
13 |
14 | JUnit is a huge success and [JUnit 5](https://junit.org/junit5) is an amazing overhaul of a tried-and-true formula.
15 | One of its most enticing new designs is [its extension model](https://nipafx.dev/junit-5-extension-model/), which is where [JUnit Pioneer](https://junit-pioneer.org/) comes in.
16 | It's a small project gathering all kinds of extensions.
17 |
18 | In this talk, we're going to take a close look at the project and we won't just stick to the technical aspects:
19 |
20 | * JUnit 5 and its extension model
21 | * Pioneer's extensions
22 | * Pioneer's mission statement
23 | * how live-streaming on Twitch grew a community
24 | * organizational style, contribution guide
25 | * code style, Git practices, release considerations
26 | * how we use Shipkit and GitHub actions for one-click releases
27 |
28 | If you're maintaining your own small open source project or are interested in a peek behind the scenes, this talk is for you.
29 |
--------------------------------------------------------------------------------
/content/videos/2016-12-06-interview-devoxx-be-2016.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: "Rewrite, Architecture, Extensions Of JUnit 5"
3 | # subtitle: "Interview At Devoxx Belgium"
4 | tags: [community, junit-5]
5 | date: 2016-12-06
6 | slug: junit-5-rewrite-architecture-extensions
7 | videoSlug: interview-devoxx-be-2016
8 | description: "What were the reasons for the rewrite? How does JUnit 5 compare to JUnit 4? What's so special about the architecture and the extension points?"
9 | searchKeywords: "junit 5"
10 | featuredImage: interview-devoxx-be-2016
11 | ---
12 |
13 | Katharine Beaumont interviewed me at Devoxx Belgium about JUnit 5.
14 | We discussed the reasons for the rewrite, the differences to JUnit 4, the underlying architecture and its potential to spawn a new generation of testing frameworks in the JVM.
15 | Last but not least we talked about missing pieces, particularly in the extension API.
16 |
--------------------------------------------------------------------------------
/content/videos/2017-03-29-nighthacking-javaland-2017.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: "Parameterized Tests in JUnit 5"
3 | # subtitle: "NightHacking Session At JavaLand 2017"
4 | tags: [junit-5]
5 | date: 2017-03-29
6 | slug: junit-5-parameterized-tests-nighthacking
7 | videoSlug: nighthacking-javaland-2017
8 | description: "At JavaLand 2017, I spent 15 minutes exploring JUnit 5's (then) brand-new parameterized test feature in a NightHacking session"
9 | searchKeywords: "JUnit 5 parameterized tests"
10 | featuredImage: nighthacking-javaland-2017
11 | repo: junit-5-demo
12 | ---
13 |
14 | Thanks Sebastian (Daschner) for inviting me to this session, exploring things live on camera is fun.
15 | (No, [really](https://twitch.tv/nipafx)!)
16 |
--------------------------------------------------------------------------------
/content/videos/2017-09-20-impressions-javazone-2017.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: "Impressions of JavaZone 2017"
3 | tags: [community]
4 | date: 2017-09-20
5 | slug: impressions-javazone-2017
6 | videoSlug: impressions-javazone-2017
7 | description: "A few impressions of my stay at JavaZone 2017 to music from [WillRock](https://willrock.bandcamp.com/)"
8 | searchKeywords: "javazone 2017"
9 | featuredImage: impressions-javazone-2017
10 | ---
11 |
12 | JavaZone 2017 was the first time I had my camera with me and I decided to put the impressions into a short video.
13 |
--------------------------------------------------------------------------------
/content/videos/2017-09-21-welcome-java-9.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: "Welcome, Java 9!"
3 | tags: [community, java-9]
4 | date: 2017-09-21
5 | slug: welcome-java-9
6 | videoSlug: welcome-java-9
7 | description: "Java 9 is out today and with other members of the community I'm throwing a welcome party. Get an all around view on the new Java release with various opinions, tips, and great sources!"
8 | searchKeywords: "Java 9"
9 | featuredImage: welcome-java-9
10 | repo: java-x-demo
11 | ---
12 |
13 | Simon Maple:
14 |
15 | * [Twitter](https://twitter.com/sjmaple)
16 | * [ZeroTurnaround](https://zeroturnaround.com/)
17 | * [Joda projects](http://www.joda.org/)
18 | * [modularity](https://www.manning.com/books/the-java-module-system?a_aid=nipa&a_bid=869915cb) [books](https://javamodularity.com/)
19 |
20 | Stephen Colebourne:
21 |
22 | * [Twitter](https://twitter.com/jodastephen)
23 | * [Blog](http://blog.joda.org/)
24 | * [OpenGamma](http://strata.opengamma.io/)
25 | * [Joda projects](http://www.joda.org/)
26 | * on modules and their names: [1](http://blog.joda.org/2017/04/java-se-9-jpms-module-naming.html), [2](http://blog.joda.org/2017/04/java-se-9-jpms-modules-are-not-artifacts.html)
27 |
28 | Christian Stein:
29 |
30 | * [Twitter](https://twitter.com/sormuras)
31 | * [JUnit 5](http://junit.org/junit5/)
32 | * [Bach (JShell-based build tool)](https://github.com/sormuras/bach)
33 |
34 | Nicolai Parlog:
35 |
36 | * [Twitter](https://twitter.com/nipafx)
37 | * [Blog](https://nipafx.dev)
38 | * [_The Java Module System_](https://www.manning.com/books/the-java-module-system?a_aid=nipa&a_bid=869915cb)
39 |
40 | Trisha Gee:
41 |
42 | * [Twitter](https://twitter.com/trisha_gee)
43 | * [Blog](https://trishagee.github.io/)
44 | * [JetBrains](https://trishagee.github.io/)
45 | * [_Real World Java 9_](https://www.youtube.com/watch?v=GkP83hvdeMk)
46 |
47 | Chris Engelbert:
48 |
49 | * [Twitter](https://twitter.com/noctarius2k)
50 | * [Hazelcast](https://hazelcast.com/)
51 |
52 | Sander Mak:
53 |
54 | * [Twitter](https://twitter.com/Sander_Mak)
55 | * [Blog](http://branchandbound.net/)
56 | * [Luminis](https://www.luminis.eu)
57 | * [_Java 9 Modularity_](https://javamodularity.com/)
58 |
59 | Jens Schauder:
60 |
61 | * [Twitter](https://twitter.com/jensschauder)
62 | * [Blog](http://blog.schauderhaft.de/)
63 | * [Spring Data](https://projects.spring.io/spring-data-jpa/)
64 | * [Pivotal](https://pivotal.io/)
65 |
66 | Monica Beckwith:
67 |
68 | * [Twitter](https://twitter.com/mon_beck)
69 | * [Code Karam](http://www.codekaram.com/)
70 |
71 | Rafael Winterhalter:
72 |
73 | * [Twitter](https://twitter.com/rafaelcodes)
74 | * [Site](http://rafael.codes/)
75 | * [ByteBuddy](http://bytebuddy.net)
76 | * [Mockito](http://mockito.org/)
77 | * [JavaZone talks](https://vimeo.com/javazone)
78 |
79 | Wayne Beaton:
80 |
81 | * [Twitter](https://twitter.com/waynebeaton)
82 | * [Eclipse](http://eclipse.org/)
83 | * [OpenJ9](https://www.eclipse.org/openj9)
84 | * [Eclipse support for Java 9](http://wiki.eclipse.org/java9)
85 |
86 | Simon Ritter:
87 |
88 | * [Twitter](https://twitter.com/speakjava)
89 | * [Azul Systems](http://azul.com/)
90 | * [_55 New Features in JDK 9_](https://www.youtube.com/watch?v=CMMzG8I23lY)
91 | * [_JDK 9: Pitfalls For The Unwary_](https://www.azul.com/jdk-9-pitfalls-for-the-unwary/)
92 | * [_JDK 9: XXtra Command Line Options_](https://www.azul.com/jdk-9-xxtra-command-line-options/)
93 |
--------------------------------------------------------------------------------
/content/videos/2017-11-16-var-java-10.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: "First contact with `var` in Java 10"
3 | tags: [java-10, var]
4 | date: 2017-11-16
5 | slug: var-java-10
6 | videoSlug: var-java-10
7 | description: "How to use `var`, where it works and where it doesn't (and why), and how it might impact readability"
8 | searchKeywords: "Java 10 var"
9 | featuredImage: var-java-10
10 | repo: java-x-demo
11 | ---
12 |
13 | Java 10 will be released in March 2018 and it comes with local-variable type inference, which means we can use `var` instead of a type name when declaring local variables.
14 | In this video I tell you how to use `var`, where it works and where it doesn't (and why), and how it might impact readability.
15 |
--------------------------------------------------------------------------------
/content/videos/2018-09-20-effective-java-00-kickoff.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: "Kicking off a series on Effective Java, Third Edition"
3 | tags: [book-club]
4 | date: 2018-09-20
5 | slug: effective-java-kickoff
6 | videoSlug: effective-java-00
7 | description: "Kick-off to [a YouTube series on Effective Java, Third Edition](https://www.youtube.com/playlist?list=PL_-IO8LOLuNqUzvXfRCWRRJBswKEbLhgN) - let's find some angles Josh didn't cover"
8 | searchKeywords: "Effective Java"
9 | featuredImage: effective-java-00
10 | repo: effective-java
11 | ---
12 |
13 | Effective Java,Third Edition, took me by surprise.
14 | After having read the second edition, I figured I would only read the new items, but I was so wrong!
15 | It sucked my right back in and I ended up rereading the entire book.
16 | I rediscovered all the details I forgot, connected the content with my personal experiences from about a decade of Java development, and had a lot of fun trying to find angles Josh hadn't covered.
17 |
18 | This inspired me to start [a YouTube series on Effective Java](https://www.youtube.com/playlist?list=PL_-IO8LOLuNqUzvXfRCWRRJBswKEbLhgN), which this video kicks off.
19 | Come with me on a journey that goes back to the roots and makes us experts in the Java core language!
20 |
--------------------------------------------------------------------------------
/content/videos/2018-09-24-effective-java-01-static-factory-methods.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: "Static Factory Methods - Effective Java, Item 1"
3 | # subtitle
4 | tags: [book-club, patterns]
5 | date: 2018-09-24
6 | slug: effective-java-static-factory-methods
7 | videoSlug: effective-java-01
8 | description: "How to use static factory methods to overcome three shortcomings of constructors"
9 | searchKeywords: "Effective Java"
10 | featuredImage: effective-java-01
11 | repo: effective-java
12 | ---
13 |
14 | Static factory methods are awesome!
15 | They allow us to overcome three shortcomings of constructors by allowing us to freely choose a name, take control over returned instances, and take control over the returned type.
16 | I use them every day.
17 |
18 | Also, I'm actually sorry about all the "actuallies". 😉
19 |
20 | Links to follow up:
21 |
22 | * [BED-Con in Berlin](http://www.bed-con.org/)
23 | * [Twitter-poll](https://twitter.com/nipafx/status/1037310344585261056)
24 | * [§1 GG](https://twitter.com/nipafx/status/1038376068728676353)
25 | * [Value-based classes](java-value-based-classes)
26 | * [Comment your &*☠# Code](comment-your-fucking-code)
27 |
--------------------------------------------------------------------------------
/content/videos/2018-10-02-java-11-new-dawn.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: "Java 11: A New Dawn - Releases, Oracle JDK vs OpenJDK, and LTS"
3 | tags: [java-11, java-next]
4 | date: 2018-10-02
5 | slug: java-11-releases-license-lts
6 | videoSlug: java-11-new-dawn
7 | description: "Oracle's announcements of the six-month release cadence and new licensing caused quite a ruckus - now that things calmed down, lets discuss where we're headed"
8 | searchKeywords: "Java 11 LTS"
9 | featuredImage: java-11-new-dawn
10 | ---
11 |
12 | Java 11 is a game changer!
13 | Not so much for technical reasons (unless you come from Java 8), but because of the new release cadence (six months), licensing (Oracle JDK vs OpenJDK), and long-term support (not free by Oracle).
14 | I discuss all of these in detail to make sure you know what to expect.
15 |
16 | Links to follow up:
17 |
18 | * [Slides](https://slides.nipafx.dev/java-next/2018-09-30-codefx@yt/)
19 | * [Java 11 migration](java-11-migration-guide)
20 | * [Incubator modules](http://openjdk.java.net/jeps/11)
21 | * [Language previews](http://openjdk.java.net/jeps/12)
22 | * [Oracle JDK vs OpenJDK](https://blogs.oracle.com/java-platform-group/oracle-jdk-releases-for-java-11-and-later)
23 | * [Red Hat stewardship](https://developers.redhat.com/blog/2018/09/24/the-future-of-java-and-openjdk-updates-without-oracle-support/)
24 |
--------------------------------------------------------------------------------
/content/videos/2018-10-09-effective-java-02-builders.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: "Use Builders... Cautiously - Effective Java, Item 2"
3 | # subtitle
4 | tags: [book-club, patterns]
5 | date: 2018-10-09
6 | slug: effective-java-builders
7 | videoSlug: effective-java-02
8 | description: "Why and how to avoid the builder pattern and how to make best use of it if you can't"
9 | searchKeywords: "Effective Java"
10 | featuredImage: effective-java-02
11 | repo: effective-java
12 | ---
13 |
14 | The builder pattern is a powerful tool to ease the instantiation of complex classes.
15 | Whether constructor parameters are too numerous, there are too many of the same type, or whether many are optional - with a builder you can make your life easier.
16 | Although, I posit, often you can make your life even easier by directly tackling the class' or constructor's complexity.
17 |
18 | In this video I show an example of how to simplify a class to make a builder obsolete, but also how to build more powerful builders that add more value than just simplifying constructor calls.
19 |
20 | Links to follow up:
21 |
22 | * [JavaZone in Oslo](https://2018.javazone.no/)
23 | * [my opinion on `Optional`](intention-revealing-code-java-8-optional)
24 | * [`Map.of` et al](java-9-tutorial/#collection-factories)
25 | * [named & default parameters in Kotlin](http://www.deadcoderising.com/kotlin-how-to-use-default-parameters-in-functions-and-constructors/)
26 | * [automaton](https://brilliant.org/wiki/finite-state-machines/)
27 | * [partial application](https://en.wikipedia.org/wiki/Partial_application)
28 | * [self types with generics](https://www.sitepoint.com/self-types-with-javas-generics/)
29 |
--------------------------------------------------------------------------------
/content/videos/2018-10-18-java-12-switch-expression.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: "First Contact with Switch Expressions in Java 12"
3 | tags: [java-12, switch]
4 | date: 2018-10-18
5 | slug: java-12-switch-expression
6 | videoSlug: switch-java-12
7 | description: "With Java 12, `switch` is no longer just a statement, but becomes an expression. Let's take a look!"
8 | searchKeywords: "Java 12 switch"
9 | featuredImage: switch-java-12
10 | repo: java-x-demo
11 | ---
12 |
13 | With `switch` becoming an expression, it can have a return value (instead of having to assign or return results) and with a lambda-like syntax that doesn't fall-through (no more `break` 🎉) and exhaustiveness checks (less `default` ) it is much more readable.
14 | So much to talk about!
15 |
16 | * [Definitive Guide To Switch Expressions](java-13-switch-expressions)
17 | * [JEP 325 - Switch Expressions](https://openjdk.java.net/jeps/325)
18 | * [JEP 12 - Preview Language and VM Features](https://openjdk.java.net/jeps/12)
19 | * [Article on `var`](java-10-var-type-inference)
20 |
--------------------------------------------------------------------------------
/content/videos/2018-10-24-robert-scholte-maven-3-4-5.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: "Maven 3 / 4 / 5 with Robert Scholte"
3 | tags: [conversation, tools]
4 | date: 2018-10-24
5 | slug: robert-scholte-maven-3-4-5
6 | videoSlug: robert-scholte-maven-3-4-5
7 | description: "Maven is one of the cornerstones of the Java ecosystem - here I talk with Robert Scholte, Chairman of the Apache Maven projects"
8 | searchKeywords: "Robert Scholte"
9 | featuredImage: robert-scholte-maven-3-4-5
10 | ---
11 |
12 | Everybody knows Maven, but few people know the developers behind it and what they plan for Java's most used build tool.
13 | I talk with Robert Scholte and he gives a glimpse of the project's inner workings as well as some ideas for Maven 4 and even 5.
14 |
15 | * [Recorded at JokerConf 2018](https://jokerconf.com/en/)
16 | * [Robert on Twitter](https://twitter.com/rfscholte)
17 | * [Maven issues to get you started](https://issues.apache.org/jira/browse/MNG-6432?jql=project%20%3D%20MNG%20AND%20labels%20in%20(starter%2C%20newbie%2C%20easyfix%2C%20beginner)%20ORDER%20BY%20created%20DESC)
18 | * [Snyk JVM Ecosystem Report 2018](https://snyk.io/blog/jvm-ecosystem-report-2018)
19 |
--------------------------------------------------------------------------------
/content/videos/2018-11-27-effective-java-03-utilities-04-singleton-05-dependency-injection.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: "Utilities, Singletons and Dependency Injection - Effective Java, Items 3-5"
3 | # subtitle
4 | tags: [book-club, patterns]
5 | date: 2018-11-27
6 | slug: effective-java-utilities-singleton-dependency-injection
7 | videoSlug: effective-java-03-04-05
8 | description: "Mildly surprising (to me), it makes sense to discuss these three patters in one video - so here it goes"
9 | searchKeywords: "Effective Java"
10 | featuredImage: effective-java-03-04-05
11 | repo: effective-java
12 | ---
13 |
14 | What do singletons, utility classes, and dependency injection have in common?
15 | All three worry about controlling instantiation - when, how, and by whom?
16 | Effective Java items 3, 4, and 5 have something to say about that.
17 |
18 | * [jDays in Gothenburg (item 4)](https://jdays.se/)
19 | * [J-Fall in Pathé Ede (item 3)](https://jfall.nl/)
20 | * [Devoxx Belgium in Antwerp (item 5)](https://devoxx.be/)
21 | * [Reduce to only element](java-stream-findfirst-findany-reduce)
22 | * [dependency injection](https://en.wikipedia.org/wiki/Dependency_injection)
23 | * [facade pattern](http://jargon.js.org/_glossary/FACADE_PATTERN.md)
24 |
--------------------------------------------------------------------------------
/content/videos/2019-02-24-java-12-experiments.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: "Java 12 Experiments (Live Stream)"
3 | tags: [java-12]
4 | date: 2019-02-24
5 | slug: java-12-experiments
6 | videoSlug: java-12-experiments-live
7 | description: "In my first live stream ever (yay!), we explored Java 12's API improvements"
8 | searchKeywords: "Java 12"
9 | featuredImage: java-12-experiments-live
10 | repo: java-x-demo
11 | ---
12 |
13 | My first [live stream](https://twitch.tv/nipafx)!
14 | We dug around in Java 12, cataloging new features and experimenting with a few of them, most notably `String::indent` and `transform`, `Collectors::teeing`, and additions to `CompletableFuture`.
15 |
16 | Thanks again to everyone who was there. 🙏
17 | I had an amazing time.
18 |
--------------------------------------------------------------------------------
/content/videos/2019-04-18-caliz-1-learning-graal.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: "Caliz I: Wrapping JVM 11 and learning about Graal AOT"
3 | tags: [performance, tools]
4 | date: 2019-04-18
5 | slug: caliz-learning-graal
6 | videoSlug: caliz-1
7 | description: "First steps toward an acceptable scripting experience with single-source-file execution and Graal native images"
8 | searchKeywords: "Caliz"
9 | featuredImage: caliz-1
10 | repo: caliz
11 | ---
12 |
13 | With Java 11's single-source-file execution and Graal's blazing fast native images (aka ahead-of-time compilation), it should be possible to create an acceptable scripting experience with Java.
14 | Here's the first part of a live stream where I did exactly that.
15 |
16 | Thanks to everyone who was there. 🙏
17 | I had an amazing time.
18 |
19 | Links to follow up:
20 |
21 | * [Caliz](https://github.com/nipafx/Caliz)
22 | * [Scripting Java](scripting-java-shebang)
23 | * [Graal AOT](https://www.graalvm.org/docs/reference-manual/aot-compilation/)
24 |
--------------------------------------------------------------------------------
/content/videos/2019-05-01-caliz-2-wrapping-graal.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: "Caliz II: Wrapping Graal AOT"
3 | tags: [performance, tools]
4 | date: 2019-05-01
5 | slug: caliz-wrapping-graal
6 | videoSlug: caliz-2
7 | description: "Extending Caliz to create native images of Java \"scripts\" (single source files) with with Graal"
8 | searchKeywords: "Caliz"
9 | featuredImage: caliz-2
10 | repo: caliz
11 | ---
12 |
13 | After I wrapped JVM 11 in the last video, it is now time to let Caliz use Graal AOT to create a native image.
14 | There are a few hurdles, though, so it took me some time.
15 |
16 | As always, thanks to everyone who was there.
17 | 🌻 I had an amazing time.
18 |
19 | Links to follow up:
20 |
21 | * [Caliz](https://github.com/nipafx/Caliz)
22 | * [Scripting Java](scripting-java-shebang)
23 | * [Graal AOT](https://www.graalvm.org/docs/reference-manual/aot-compilation/)
24 |
--------------------------------------------------------------------------------
/content/videos/2019-05-16-caliz-3-background-compilation.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: "Caliz III: Hashing scripts and background compilation"
3 | tags: [performance, tools]
4 | date: 2019-05-16
5 | slug: caliz-background-compilation
6 | videoSlug: caliz-3
7 | description: "Letting Caliz store native images and only create them for a given Java \"script\" (single source file) if needed"
8 | searchKeywords: "Caliz"
9 | featuredImage: caliz-3
10 | repo: caliz
11 | ---
12 |
13 | After I wrapping JVM 11 and Graal AOT in the last two videos, it is now time to determine for a given script, which way to go.
14 |
15 | Thanks again to everyone who was there for the amazing time. 🏆
16 |
17 | Links to follow up:
18 |
19 | * [Caliz](https://github.com/nipafx/Caliz)
20 | * [Scripting Java](scripting-java-shebang)
21 | * [Graal AOT](https://www.graalvm.org/docs/reference-manual/aot-compilation/)
22 |
--------------------------------------------------------------------------------
/content/videos/2019-05-26-jpms-sander-mak.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: "The Java Module System with Sander Mak"
3 | tags: [conversation, j_ms]
4 | date: 2019-05-26
5 | slug: java-module-system-sander-mak
6 | videoSlug: jpms-sander-mak
7 | description: "At J-Fall 2018 I talked to Sander Mak, modularity expert at Luminis, about the Java module system (J_MS), its adoption, how it compares to OSGi, and more."
8 | searchKeywords: "JMS OSGi"
9 | featuredImage: jpms-sander-mak
10 | ---
11 |
12 | Some links to follow up:
13 |
14 | * [J-Fall](https://jfall.nl/) 2018
15 | * [Sander's talk (in Dutch)](https://www.youtube.com/watch?v=CNypJD-41Ng)
16 | * [Sander on Twitter](https://twitter.com/Sander_Mak)
17 | * Sander Mak's book [_Java 9 Modularity_](https://javamodularity.com/)
18 | * my book [_The Java Module System_](https://www.manning.com/books/the-java-module-system?a_aid=nipa&a_bid=869915cb)
19 |
--------------------------------------------------------------------------------
/content/videos/2019-09-18-keynote-blip-code-one-2019.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: "How We Upgraded From Java 8 And Why You Can (And Should) Do It Too"
3 | # subtitle: "Code One Keynote Blip"
4 | tags: [community, migration]
5 | date: 2019-09-18
6 | slug: upgrade-from-java-8
7 | videoSlug: keynote-blip-code-one-2019
8 | description: "My two minutes of fame during the Oracle Code One 2019 keynote"
9 | searchKeywords: "code one 2019"
10 | featuredImage: keynote-blip-code-one-2019
11 | ---
12 |
13 | Is it vain to say that I'm really proud that I got asked by Oracle's JVM team to record a blip for the keynote?
14 | Because I am!
15 | 😊
16 |
--------------------------------------------------------------------------------
/content/videos/2020-04-07-oliver-drotbohm-modularity.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: "Modularity with Oliver Drotbohm"
3 | tags: [architecture, conversation, j_ms]
4 | date: 2020-04-07
5 | slug: oliver-drotbohm-modularity
6 | videoSlug: oliver-drotbohm-modularity
7 | description: "Oliver and I discuss modularity in Java with a focus on the Java module system"
8 | searchKeywords: "Java modularity"
9 | featuredImage: oliver-drotbohm-modularity
10 | ---
11 |
12 | [Oliver](https://twitter.com/odrotbohm) is Senior Principal Software Engineer at Pivotal, Java Champion, and OpenSource enthusiast.
13 | He's an expert in all things Spring, data, DDD, REST, and software architecture.
14 | He's into drums and music and is the inventor of the `@soundtrack` annotation.
15 |
16 | * [the tweet that started it all](https://twitter.com/lukaseder/status/1238393568730939392)
17 | * [Oliver's reply](https://twitter.com/odrotbohm/status/1238480137756332039)
18 | * [Salespoint](https://github.com/st-tu-dresden/salespoint)
19 | * [Moduliths](https://github.com/odrotbohm/moduliths)
20 | * [tabs better than spaces](https://www.reddit.com/r/javascript/comments/c8drjo/nobody_talks_about_the_real_reason_to_use_tabs/)
21 | * [J_MS issue summary](https://openjdk.java.net/projects/jigsaw/spec/issues/)
22 | * [J_MS'ed application](https://blog.disy.net/java-modules-modularization-1/)
23 |
--------------------------------------------------------------------------------
/content/videos/2020-04-28-generics-1-basics.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: "Java Generics I - The Basics"
3 | tags: [generics]
4 | date: 2020-04-28
5 | slug: java-generics-basics
6 | videoSlug: generics-1
7 | description: "First part of a short series on Java Generics - this one explains the basics"
8 | searchKeywords: "Java generics"
9 | featuredImage: generics-1
10 | ---
11 |
12 | Nothing more to say, gotta watch the video. 😃
13 |
--------------------------------------------------------------------------------
/content/videos/2021-02-11-brian-goetz-25h.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: "Java's Quirks and Wrong (?) Defaults with Brian Goetz"
3 | # subtitle: "Today's problems come from yesterday's solutions"
4 | tags: [conversation, migration, optional, serialization]
5 | date: 2021-02-11
6 | slug: 25h-brian-goetz
7 | videoSlug: brian-goetz-25h
8 | description: "Mutability, nullability, serialization, primitives - Nicolai Parlog discusses with Java language architect Brian Goetz why Java is the way it is."
9 | intro: "Mutability, nullability, serialization, primitives - Java seems to have gotten most things wrong. But could it have been successful otherwise? Brian Goetz and I discuss why Java is the way it is."
10 | featuredImage: brian-goetz-25h
11 | ---
12 |
13 | The runner-up for the video title was:
14 |
15 | > Today's problems come from yesterday's solutions.
16 |
17 | At [the 25-hour live stream](25h-java), Brian and I talk about a few things that annoy Java developers today, why they are the way they are, and what could have been done differently. Our topics (link to timestamps in video):
18 |
19 | * [What's wrong with serialization?](https://www.youtube.com/watch?v=ZyTH8uCziI4&t=03m28s)
20 | * [How it could've been better](https://www.youtube.com/watch?v=ZyTH8uCziI4&t=12m06s)
21 | * [`null` - the hole in Java's type system](https://www.youtube.com/watch?v=ZyTH8uCziI4&t=19m20s)
22 | * [Why that's not easy to fix](https://www.youtube.com/watch?v=ZyTH8uCziI4&t=23m20s)
23 | * [Strict mode, compatibility, trade-offs](https://www.youtube.com/watch?v=ZyTH8uCziI4&t=28m01s)
24 | * [Nominal vs structural typing](https://www.youtube.com/watch?v=ZyTH8uCziI4&t=34m03s)
25 | * [Java got all the defaults wrong](https://www.youtube.com/watch?v=ZyTH8uCziI4&t=36m23s)
26 | * [Primitives then and now](https://www.youtube.com/watch?v=ZyTH8uCziI4&t=43m10s)
27 | * [Brian's favorite language](https://www.youtube.com/watch?v=ZyTH8uCziI4&t=48m16s)
28 |
29 |
30 |
31 |
41 |
42 |
57 |
--------------------------------------------------------------------------------
/genealogists/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 | 4.0.0
6 |
7 |
8 | org.codefx.java-after-eight
9 | parent
10 | 1.0-SNAPSHOT
11 |
12 |
13 | org.codefx.java_after_eight
14 | genealogists
15 |
16 |
17 |
18 | org.codefx.java_after_eight
19 | genealogy
20 | 1.0-SNAPSHOT
21 |
22 |
23 |
24 |
25 |
26 |
27 | maven-jar-plugin
28 |
29 | genealogists
30 | ../jars
31 |
32 |
33 |
34 | maven-javadoc-plugin
35 |
36 |
37 |
38 | javadoc
39 |
40 | package
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
--------------------------------------------------------------------------------
/genealogists/src/main/java/org/codefx/java_after_eight/genealogists/package-info.java:
--------------------------------------------------------------------------------
1 | /**
2 | * For more possible genealogists, see:
3 | * - text similarities: https://medium.com/@adriensieg/text-similarities-da019229c894
4 | * - Stanford CoreNLP: https://github.com/stanfordnlp/CoreNLP
5 | */
6 | package org.codefx.java_after_eight.genealogists;
7 |
--------------------------------------------------------------------------------
/genealogists/src/main/java/org/codefx/java_after_eight/genealogists/random/RandomGenealogist.java:
--------------------------------------------------------------------------------
1 | package org.codefx.java_after_eight.genealogists.random;
2 |
3 | import org.codefx.java_after_eight.genealogist.Genealogist;
4 | import org.codefx.java_after_eight.genealogist.RelationType;
5 | import org.codefx.java_after_eight.genealogist.TypedRelation;
6 | import org.codefx.java_after_eight.post.Post;
7 |
8 | import java.util.Random;
9 |
10 | import static java.util.Objects.requireNonNull;
11 |
12 | public class RandomGenealogist implements Genealogist {
13 |
14 | private static final RelationType TYPE = new RelationType("random");
15 |
16 | private final Random random;
17 |
18 | public RandomGenealogist(Random random) {
19 | this.random = requireNonNull(random);
20 | }
21 |
22 | @Override
23 | public TypedRelation infer(Post post1, Post post2) {
24 | long score = random.nextLong();
25 | return new TypedRelation(post1, post2, TYPE, score);
26 | }
27 |
28 | }
29 |
--------------------------------------------------------------------------------
/genealogists/src/main/java/org/codefx/java_after_eight/genealogists/random/RandomGenealogistService.java:
--------------------------------------------------------------------------------
1 | package org.codefx.java_after_eight.genealogists.random;
2 |
3 | import org.codefx.java_after_eight.genealogist.Genealogist;
4 | import org.codefx.java_after_eight.genealogist.GenealogistService;
5 | import org.codefx.java_after_eight.post.Post;
6 |
7 | import java.util.Collection;
8 | import java.util.Random;
9 |
10 | public class RandomGenealogistService implements GenealogistService {
11 |
12 | @Override
13 | public Genealogist procure(Collection posts) {
14 | Random random = new Random();
15 | return new RandomGenealogist(random);
16 | }
17 |
18 | }
--------------------------------------------------------------------------------
/genealogists/src/main/java/org/codefx/java_after_eight/genealogists/repo/RepoGenealogist.java:
--------------------------------------------------------------------------------
1 | package org.codefx.java_after_eight.genealogists.repo;
2 |
3 | import org.codefx.java_after_eight.genealogist.Genealogist;
4 | import org.codefx.java_after_eight.genealogist.RelationType;
5 | import org.codefx.java_after_eight.genealogist.TypedRelation;
6 | import org.codefx.java_after_eight.post.Article;
7 | import org.codefx.java_after_eight.post.Post;
8 | import org.codefx.java_after_eight.post.Repository;
9 | import org.codefx.java_after_eight.post.Video;
10 |
11 | import java.util.Objects;
12 | import java.util.Optional;
13 |
14 | public class RepoGenealogist implements Genealogist {
15 |
16 | private static final RelationType TYPE = new RelationType("repo");
17 |
18 | @Override
19 | public TypedRelation infer(Post post1, Post post2) {
20 | long score = determineScore(post1, post2);
21 | return new TypedRelation(post1, post2, TYPE, score);
22 | }
23 |
24 | private long determineScore(Post post1, Post post2) {
25 | Optional repo1 = getRepository(post1);
26 | Optional repo2 = getRepository(post2);
27 |
28 | if (repo1.isPresent() != repo2.isPresent())
29 | return 0;
30 | // at this point, either both are empty or both are non-empty
31 | if (!repo1.isPresent())
32 | return 20;
33 | return Objects.equals(repo1, repo2) ? 100 : 50;
34 | }
35 |
36 | private Optional getRepository(Post post) {
37 | if (post instanceof Article)
38 | return ((Article) post).repository();
39 | if (post instanceof Video)
40 | return ((Video) post).repository();
41 | return Optional.empty();
42 | }
43 |
44 | }
45 |
--------------------------------------------------------------------------------
/genealogists/src/main/java/org/codefx/java_after_eight/genealogists/repo/RepoGenealogistService.java:
--------------------------------------------------------------------------------
1 | package org.codefx.java_after_eight.genealogists.repo;
2 |
3 | import org.codefx.java_after_eight.genealogist.Genealogist;
4 | import org.codefx.java_after_eight.genealogist.GenealogistService;
5 | import org.codefx.java_after_eight.post.Post;
6 |
7 | import java.util.Collection;
8 |
9 | public class RepoGenealogistService implements GenealogistService {
10 |
11 | @Override
12 | public Genealogist procure(Collection posts) {
13 | return new RepoGenealogist();
14 | }
15 |
16 | }
17 |
--------------------------------------------------------------------------------
/genealogists/src/main/java/org/codefx/java_after_eight/genealogists/silly/SillyGenealogist.java:
--------------------------------------------------------------------------------
1 | package org.codefx.java_after_eight.genealogists.silly;
2 |
3 | import org.codefx.java_after_eight.genealogist.Genealogist;
4 | import org.codefx.java_after_eight.genealogist.RelationType;
5 | import org.codefx.java_after_eight.genealogist.TypedRelation;
6 | import org.codefx.java_after_eight.post.Post;
7 |
8 | import java.util.HashSet;
9 | import java.util.Set;
10 |
11 | import static java.lang.Math.round;
12 | import static java.util.stream.Collectors.toSet;
13 |
14 | public class SillyGenealogist implements Genealogist {
15 |
16 | private static final RelationType TYPE = new RelationType("silly");
17 |
18 | @Override
19 | public TypedRelation infer(Post post1, Post post2) {
20 | Set post1Letters = titleLetters(post1);
21 | Set post2Letters = titleLetters(post2);
22 | Set intersection = new HashSet<>(post1Letters);
23 | intersection.retainAll(post2Letters);
24 | long score = round((100.0 * intersection.size()) / post1Letters.size());
25 |
26 | return new TypedRelation(post1, post2, TYPE, score);
27 | }
28 |
29 | private static Set titleLetters(Post post) {
30 | return post
31 | .title()
32 | .text()
33 | .toLowerCase()
34 | .chars().boxed()
35 | .collect(toSet());
36 | }
37 |
38 | }
39 |
--------------------------------------------------------------------------------
/genealogists/src/main/java/org/codefx/java_after_eight/genealogists/silly/SillyGenealogistService.java:
--------------------------------------------------------------------------------
1 | package org.codefx.java_after_eight.genealogists.silly;
2 |
3 | import org.codefx.java_after_eight.genealogist.Genealogist;
4 | import org.codefx.java_after_eight.genealogist.GenealogistService;
5 | import org.codefx.java_after_eight.post.Post;
6 |
7 | import java.util.Collection;
8 |
9 | public class SillyGenealogistService implements GenealogistService {
10 |
11 | @Override
12 | public Genealogist procure(Collection posts) {
13 | return new SillyGenealogist();
14 | }
15 |
16 | }
17 |
--------------------------------------------------------------------------------
/genealogists/src/main/java/org/codefx/java_after_eight/genealogists/tags/TagGenealogist.java:
--------------------------------------------------------------------------------
1 | package org.codefx.java_after_eight.genealogists.tags;
2 |
3 | import org.codefx.java_after_eight.genealogist.Genealogist;
4 | import org.codefx.java_after_eight.genealogist.RelationType;
5 | import org.codefx.java_after_eight.genealogist.TypedRelation;
6 | import org.codefx.java_after_eight.post.Post;
7 | import org.codefx.java_after_eight.post.Tag;
8 |
9 | import java.util.Set;
10 |
11 | import static java.lang.Math.round;
12 | import static java.util.stream.Collectors.toSet;
13 |
14 | public class TagGenealogist implements Genealogist {
15 |
16 | private static final RelationType TYPE = new RelationType("tag");
17 |
18 | @Override
19 | public TypedRelation infer(Post post1, Post post2) {
20 | Set post2Tags = post2.tags().collect(toSet());
21 | long numberOfSharedTags = post1
22 | .tags()
23 | .filter(post2Tags::contains)
24 | .count();
25 | long numberOfPost1Tags = post1.tags().count();
26 | long score = round((100.0 * 2 * numberOfSharedTags) / (numberOfPost1Tags + post2Tags.size()));
27 | return new TypedRelation(post1, post2, TYPE, score);
28 | }
29 |
30 | }
31 |
--------------------------------------------------------------------------------
/genealogists/src/main/java/org/codefx/java_after_eight/genealogists/tags/TagGenealogistService.java:
--------------------------------------------------------------------------------
1 | package org.codefx.java_after_eight.genealogists.tags;
2 |
3 | import org.codefx.java_after_eight.genealogist.Genealogist;
4 | import org.codefx.java_after_eight.genealogist.GenealogistService;
5 | import org.codefx.java_after_eight.post.Post;
6 |
7 | import java.util.Collection;
8 |
9 | public class TagGenealogistService implements GenealogistService {
10 |
11 | @Override
12 | public Genealogist procure(Collection posts) {
13 | return new TagGenealogist();
14 | }
15 |
16 | }
17 |
--------------------------------------------------------------------------------
/genealogists/src/main/java/org/codefx/java_after_eight/genealogists/type/TypeGenealogist.java:
--------------------------------------------------------------------------------
1 | package org.codefx.java_after_eight.genealogists.type;
2 |
3 | import org.codefx.java_after_eight.genealogist.Genealogist;
4 | import org.codefx.java_after_eight.genealogist.RelationType;
5 | import org.codefx.java_after_eight.genealogist.TypedRelation;
6 | import org.codefx.java_after_eight.post.Post;
7 |
8 | public class TypeGenealogist implements Genealogist {
9 |
10 | private static final RelationType TYPE = new RelationType("type");
11 |
12 | @Override
13 | public TypedRelation infer(Post post1, Post post2) {
14 | long score = 0;
15 | switch (post2.getClass().getSimpleName()) {
16 | case "Article":
17 | score = 50;
18 | break;
19 | case "Video":
20 | score = 90;
21 | break;
22 | case "Talk":
23 | score = 20;
24 | break;
25 | }
26 |
27 | return new TypedRelation(post1, post2, TYPE, score);
28 | }
29 |
30 | }
31 |
--------------------------------------------------------------------------------
/genealogists/src/main/java/org/codefx/java_after_eight/genealogists/type/TypeGenealogistService.java:
--------------------------------------------------------------------------------
1 | package org.codefx.java_after_eight.genealogists.type;
2 |
3 | import org.codefx.java_after_eight.genealogist.Genealogist;
4 | import org.codefx.java_after_eight.genealogist.GenealogistService;
5 | import org.codefx.java_after_eight.post.Post;
6 |
7 | import java.util.Collection;
8 |
9 | public class TypeGenealogistService implements GenealogistService {
10 |
11 | @Override
12 | public Genealogist procure(Collection posts) {
13 | return new TypeGenealogist();
14 | }
15 |
16 | }
17 |
--------------------------------------------------------------------------------
/genealogists/src/main/resources/META-INF/services/org.codefx.java_after_eight.genealogist.GenealogistService:
--------------------------------------------------------------------------------
1 | # org.codefx.java_after_eight.genealogists.repo.RepoGenealogist
2 | # org.codefx.java_after_eight.genealogists.silly.SillyGenealogistService
3 | org.codefx.java_after_eight.genealogists.tags.TagGenealogistService
4 | # org.codefx.java_after_eight.genealogists.type.TypeGenealogist
5 |
--------------------------------------------------------------------------------
/genealogy/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 | 4.0.0
6 |
7 |
8 | org.codefx.java-after-eight
9 | parent
10 | 1.0-SNAPSHOT
11 |
12 |
13 | org.codefx.java_after_eight
14 | genealogy
15 |
16 |
17 |
18 |
19 | maven-jar-plugin
20 |
21 | genealogy
22 | ../jars
23 |
24 |
25 | true
26 | org.codefx.java_after_eight.Main
27 |
28 |
29 |
30 |
31 |
32 | maven-javadoc-plugin
33 |
34 |
35 |
36 | javadoc
37 |
38 | package
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 | org.junit.jupiter
49 | junit-jupiter
50 | test
51 |
52 |
53 | org.junit.jupiter
54 | junit-jupiter-params
55 | test
56 |
57 |
58 | org.mockito
59 | mockito-core
60 | test
61 |
62 |
63 | org.mockito
64 | mockito-junit-jupiter
65 | test
66 |
67 |
68 | org.assertj
69 | assertj-core
70 | test
71 |
72 |
73 |
74 |
75 |
--------------------------------------------------------------------------------
/genealogy/src/main/java/org/codefx/java_after_eight/Config.java:
--------------------------------------------------------------------------------
1 | package org.codefx.java_after_eight;
2 |
3 | import java.io.IOException;
4 | import java.io.UncheckedIOException;
5 | import java.nio.file.Files;
6 | import java.nio.file.Path;
7 | import java.nio.file.Paths;
8 | import java.util.Optional;
9 | import java.util.concurrent.CompletableFuture;
10 |
11 | public class Config {
12 |
13 | private static final String CONFIG_FILE_NAME = "recommendations.config";
14 |
15 | private final Path articleFolder;
16 | private final Path talkFolder;
17 | private final Path videoFolder;
18 | private final Optional outputFile;
19 |
20 | private Config(String[] raw) {
21 | if (raw.length == 0)
22 | throw new IllegalArgumentException("No article path defined.");
23 |
24 | this.articleFolder = readFolder(raw[0]);
25 | this.talkFolder = readFolder(raw[1]);
26 | this.videoFolder = readFolder(raw[2]);
27 |
28 | Optional outputFile = raw.length >= 4
29 | ? Optional.of(raw[3])
30 | : Optional.empty();
31 | this.outputFile = outputFile
32 | .map(file -> Paths.get(System.getProperty("user.dir")).resolve(file));
33 | this.outputFile.ifPresent(file -> {
34 | boolean notWritable = Files.exists(file) && !Files.isWritable(file);
35 | if (notWritable)
36 | throw new IllegalArgumentException("Output path is not writable: " + this.outputFile.get());
37 | });
38 | }
39 |
40 | private static Path readFolder(String raw) {
41 | Path folder = Paths.get(raw);
42 | if (!Files.exists(folder))
43 | throw new IllegalArgumentException("Path doesn't exist: " + folder);
44 | if (!Files.isDirectory(folder))
45 | throw new IllegalArgumentException("Path is no directory: " + folder);
46 | return folder;
47 | }
48 |
49 | public Path articleFolder() {
50 | return articleFolder;
51 | }
52 |
53 | public Path talkFolder() {
54 | return talkFolder;
55 | }
56 |
57 | public Path videoFolder() {
58 | return videoFolder;
59 | }
60 |
61 | public Optional outputFile() {
62 | return outputFile;
63 | }
64 |
65 | public static CompletableFuture create(String[] args) {
66 | CompletableFuture rawConfig = args.length > 0
67 | ? CompletableFuture.completedFuture(args)
68 | : readProjectConfig()
69 | .exceptionally(__ -> readUserConfig().join())
70 | .exceptionally(__ -> new String[0]);
71 |
72 | return rawConfig
73 | .thenApply(Config::new);
74 | }
75 |
76 | private static CompletableFuture readProjectConfig() {
77 | Path workingDir = Paths.get(System.getProperty("user.dir")).resolve(CONFIG_FILE_NAME);
78 | return readConfig(workingDir);
79 | }
80 |
81 | private static CompletableFuture readUserConfig() {
82 | Path workingDir = Paths.get(System.getProperty("user.home")).resolve(CONFIG_FILE_NAME);
83 | return readConfig(workingDir);
84 | }
85 |
86 | private static CompletableFuture readConfig(Path workingDir) {
87 | return CompletableFuture.supplyAsync(() -> {
88 | try {
89 | return Files.readAllLines(workingDir).toArray(new String[0]);
90 | } catch (IOException ex) {
91 | throw new UncheckedIOException(ex);
92 | }
93 | });
94 | }
95 |
96 | }
97 |
--------------------------------------------------------------------------------
/genealogy/src/main/java/org/codefx/java_after_eight/Main.java:
--------------------------------------------------------------------------------
1 | package org.codefx.java_after_eight;
2 |
3 | import org.codefx.java_after_eight.genealogist.Genealogist;
4 | import org.codefx.java_after_eight.genealogist.GenealogistService;
5 | import org.codefx.java_after_eight.genealogy.Genealogy;
6 | import org.codefx.java_after_eight.genealogy.Relation;
7 | import org.codefx.java_after_eight.genealogy.Weights;
8 | import org.codefx.java_after_eight.post.Post;
9 | import org.codefx.java_after_eight.post.factories.ArticleFactory;
10 | import org.codefx.java_after_eight.post.factories.TalkFactory;
11 | import org.codefx.java_after_eight.post.factories.VideoFactory;
12 | import org.codefx.java_after_eight.recommendation.Recommendation;
13 | import org.codefx.java_after_eight.recommendation.Recommender;
14 |
15 | import java.nio.file.Files;
16 | import java.nio.file.Path;
17 | import java.util.ArrayList;
18 | import java.util.Collection;
19 | import java.util.List;
20 | import java.util.ServiceLoader;
21 | import java.util.stream.Stream;
22 |
23 | import static java.util.stream.Collectors.joining;
24 | import static java.util.stream.Collectors.toList;
25 | import static org.codefx.java_after_eight.Utils.concat;
26 |
27 | public class Main {
28 |
29 | public static void main(String[] args) {
30 | System.out.println(ProcessDetails.details());
31 |
32 | Config config = Config.create(args).join();
33 | Genealogy genealogy = createGenealogy(config.articleFolder(), config.talkFolder(), config.videoFolder());
34 | Recommender recommender = new Recommender();
35 |
36 | Stream relations = genealogy.inferRelations();
37 | Stream recommendations = recommender.recommend(relations, 3);
38 | String recommendationsAsJson = recommendationsToJson(recommendations);
39 |
40 | if (config.outputFile().isPresent())
41 | Utils.uncheckedFilesWrite(config.outputFile().get(), recommendationsAsJson);
42 | else
43 | System.out.println(recommendationsAsJson);
44 | }
45 |
46 | private static Genealogy createGenealogy(Path articleFolder, Path talkFolder, Path videoFolder) {
47 | List posts = concat(
48 | markdownFilesIn(articleFolder).map(ArticleFactory::createArticle),
49 | markdownFilesIn(talkFolder).map(TalkFactory::createTalk),
50 | markdownFilesIn(videoFolder).map(VideoFactory::createVideo)
51 | ).collect(toList());
52 | Collection genealogists = getGenealogists(posts);
53 | return new Genealogy(posts, genealogists, Weights.allEqual());
54 | }
55 |
56 | private static Stream markdownFilesIn(Path folder) {
57 | return Utils.uncheckedFilesList(folder)
58 | .filter(Files::isRegularFile)
59 | .filter(file -> file.toString().endsWith(".md"));
60 | }
61 |
62 | private static Collection getGenealogists(Collection posts) {
63 | List genealogists = new ArrayList<>();
64 | ServiceLoader
65 | .load(GenealogistService.class)
66 | .forEach(service -> genealogists.add(service.procure(posts)));
67 | if (genealogists.isEmpty())
68 | throw new IllegalArgumentException("No genealogists found.");
69 | return genealogists;
70 | }
71 |
72 | private static String recommendationsToJson(Stream recommendations) {
73 | String frame = "[\n$RECOMMENDATIONS\n]";
74 | String recommendation = "" +
75 | "\t{" +
76 | "\n\t\t\"title\": \"$TITLE\",\n" +
77 | "\t\t\"recommendations\": [\n" +
78 | "$RECOMMENDED_POSTS\n" +
79 | "\t\t]\n" +
80 | "\t}";
81 | String recommendedPost = "" +
82 | "\t\t\t{ \"title\": \"$TITLE\" }";
83 |
84 | String recs = recommendations
85 | .map(rec -> {
86 | String posts = rec
87 | .recommendedPosts()
88 | .map(recArt -> recArt.title().text())
89 | .map(recTitle -> recommendedPost.replace("$TITLE", recTitle))
90 | .collect(joining(",\n"));
91 | return recommendation
92 | .replace("$TITLE", rec.post().title().text())
93 | .replace("$RECOMMENDED_POSTS", posts);
94 | })
95 | .collect(joining(",\n"));
96 | return frame.replace("$RECOMMENDATIONS", recs);
97 | }
98 |
99 | }
100 |
--------------------------------------------------------------------------------
/genealogy/src/main/java/org/codefx/java_after_eight/ProcessDetails.java:
--------------------------------------------------------------------------------
1 | package org.codefx.java_after_eight;
2 |
3 | import java.io.BufferedReader;
4 | import java.io.File;
5 | import java.io.IOException;
6 | import java.io.InputStream;
7 | import java.io.InputStreamReader;
8 | import java.lang.management.ManagementFactory;
9 | import java.lang.management.RuntimeMXBean;
10 | import java.lang.reflect.Field;
11 | import java.lang.reflect.Method;
12 | import java.util.Optional;
13 |
14 | import static java.lang.String.format;
15 |
16 | public class ProcessDetails {
17 |
18 | public static String details() {
19 | return format(
20 | "Process ID: %s | Major Java version: %s",
21 | getPid().map(Object::toString).orElse("unknown"),
22 | getMajorJavaVersion().map(Object::toString).orElse("unknown"));
23 | }
24 |
25 | public static Optional getPid() {
26 | Optional pid = getPidFromMxBeanName();
27 | if (pid.isPresent())
28 | return pid;
29 | pid = getPidFromMxBeanInternal();
30 | if (pid.isPresent())
31 | return pid;
32 | pid = getPidFromProcSelfSymlink();
33 | if (pid.isPresent())
34 | return pid;
35 | pid = getPidFromBashPid();
36 | if (pid.isPresent())
37 | return pid;
38 |
39 | return Optional.empty();
40 | }
41 |
42 | private static Optional getPidFromMxBeanName() {
43 | // on many VMs `ManagementFactory.getRuntimeMXBean().getName()`
44 | // returns something like 1234@localhost
45 | String[] pidAndHost = ManagementFactory.getRuntimeMXBean().getName().split("@");
46 | try {
47 | return Optional.of(Long.parseLong(pidAndHost[0]));
48 | } catch (NumberFormatException ex) {
49 | return Optional.empty();
50 | }
51 | }
52 |
53 | private static Optional getPidFromMxBeanInternal() {
54 | // crosses fingers
55 | try {
56 | RuntimeMXBean runtime = ManagementFactory.getRuntimeMXBean();
57 | Field jvm_field = runtime.getClass().getDeclaredField("jvm");
58 | jvm_field.setAccessible(true);
59 | Object mgmt = jvm_field.get(runtime);
60 |
61 | Method pid_method = mgmt.getClass().getDeclaredMethod("getProcessId");
62 | pid_method.setAccessible(true);
63 | int pid = (int) pid_method.invoke(mgmt);
64 |
65 | return Optional.of((long) pid);
66 | } catch (ClassCastException | ReflectiveOperationException ex) {
67 | return Optional.empty();
68 | }
69 | }
70 |
71 | private static Optional getPidFromProcSelfSymlink() {
72 | try {
73 | String pid = new File("/proc/self").getCanonicalFile().getName();
74 | return Optional.of(Long.parseLong(pid));
75 | } catch (IOException | NumberFormatException ex) {
76 | return Optional.empty();
77 | }
78 | }
79 |
80 | private static Optional getPidFromBashPid() {
81 | // if we're on Linux, this should work on all POSIX shells
82 | try {
83 | InputStream echoPid = new ProcessBuilder("sh", "-c", "echo $PPID").start().getInputStream();
84 | String pid = new BufferedReader(new InputStreamReader(echoPid)).readLine();
85 | return Optional.of(Long.parseLong(pid));
86 | } catch (IOException | NumberFormatException ex) {
87 | return Optional.empty();
88 | }
89 | }
90 |
91 | public static Optional getMajorJavaVersion() {
92 | try {
93 | String version = System.getProperty("java.version");
94 | if (version.startsWith("1."))
95 | return Optional.of(Integer.parseInt(version.substring(2, 3)));
96 |
97 | if (version.contains("."))
98 | return Optional.of(Integer.parseInt(version.split("\\.")[0]));
99 |
100 | // hail mary
101 | return Optional.of(Integer.parseInt(version));
102 | } catch (NumberFormatException ex) {
103 | return Optional.empty();
104 | }
105 | }
106 |
107 | }
108 |
--------------------------------------------------------------------------------
/genealogy/src/main/java/org/codefx/java_after_eight/Utils.java:
--------------------------------------------------------------------------------
1 | package org.codefx.java_after_eight;
2 |
3 | import java.io.IOException;
4 | import java.io.UncheckedIOException;
5 | import java.nio.charset.StandardCharsets;
6 | import java.nio.file.Files;
7 | import java.nio.file.Path;
8 | import java.util.Arrays;
9 | import java.util.List;
10 | import java.util.Objects;
11 | import java.util.Optional;
12 | import java.util.concurrent.atomic.AtomicReference;
13 | import java.util.function.BiPredicate;
14 | import java.util.stream.Collector;
15 | import java.util.stream.Stream;
16 |
17 | import static java.lang.String.format;
18 |
19 | public final class Utils {
20 |
21 | private Utils() {
22 | // private constructor to prevent accidental instantiation of utility class
23 | }
24 |
25 | public static String removeOuterQuotationMarks(String string) {
26 | return string.replaceAll("^\"|\"$", "");
27 | }
28 |
29 | public static Stream uncheckedFilesList(Path dir) {
30 | try {
31 | return Files.list(dir);
32 | } catch (IOException ex) {
33 | throw new UncheckedIOException(ex);
34 | }
35 | }
36 |
37 | public static void uncheckedFilesWrite(Path path, String content) {
38 | try {
39 | Files.write(path, Arrays.asList(content), StandardCharsets.UTF_8);
40 | } catch (IOException ex) {
41 | throw new UncheckedIOException(ex);
42 | }
43 | }
44 |
45 | public static List uncheckedFilesReadAllLines(Path file) {
46 | try {
47 | return Files.readAllLines(file, StandardCharsets.UTF_8);
48 | } catch (IOException ex) {
49 | throw new UncheckedIOException(ex);
50 | }
51 | }
52 |
53 | public static Stream uncheckedFilesLines(Path file) {
54 | try {
55 | return Files.lines(file, StandardCharsets.UTF_8);
56 | } catch (IOException ex) {
57 | throw new UncheckedIOException(ex);
58 | }
59 | }
60 |
61 | @SuppressWarnings("unchecked")
62 | public static Stream concat(Stream extends ELEMENT>... streams) {
63 | return Stream.of(streams).flatMap(s -> s);
64 | }
65 |
66 | public static Collector> collectEqualElement() {
67 | return collectEqualElement(Objects::equals);
68 | }
69 |
70 | public static Collector> collectEqualElement(
71 | BiPredicate equals) {
72 | return Collector.of(
73 | AtomicReference::new,
74 | (AtomicReference left, ELEMENT right) -> {
75 | if (left.get() != null && !equals.test(left.get(), right))
76 | throw new IllegalArgumentException(
77 | format("Unequal elements in stream: %s vs %s", left.get(), right));
78 | left.set(right);
79 | },
80 | (AtomicReference left, AtomicReference right) -> {
81 | if (left.get() != null && right.get() != null && !equals.test(left.get(), right.get()))
82 | throw new IllegalArgumentException(
83 | format("Unequal elements in stream: %s vs %s", left.get(), right.get()));
84 | return left.get() != null ? left : right;
85 | },
86 | reference -> Optional.ofNullable(reference.get())
87 | );
88 | }
89 |
90 | }
91 |
--------------------------------------------------------------------------------
/genealogy/src/main/java/org/codefx/java_after_eight/genealogist/Genealogist.java:
--------------------------------------------------------------------------------
1 | package org.codefx.java_after_eight.genealogist;
2 |
3 | import org.codefx.java_after_eight.post.Post;
4 |
5 | public interface Genealogist {
6 |
7 | TypedRelation infer(Post post1, Post post2);
8 |
9 | }
10 |
--------------------------------------------------------------------------------
/genealogy/src/main/java/org/codefx/java_after_eight/genealogist/GenealogistService.java:
--------------------------------------------------------------------------------
1 | package org.codefx.java_after_eight.genealogist;
2 |
3 | import org.codefx.java_after_eight.post.Post;
4 |
5 | import java.util.Collection;
6 |
7 | /**
8 | * Used as a service to create {@link Genealogist}s - must have a public parameterless constructor.
9 | *
10 | *