Skip to content

content(blog): add Railway-Oriented Programming in Java post#59

Merged
domix merged 2 commits intomainfrom
feature/blog/post/railway_oriented_programming
Mar 5, 2026
Merged

content(blog): add Railway-Oriented Programming in Java post#59
domix merged 2 commits intomainfrom
feature/blog/post/railway_oriented_programming

Conversation

@domix
Copy link
Owner

@domix domix commented Mar 5, 2026

Introduce a new article covering the ROP pattern using pure Java:
two-track Result<T,E> type, flatMap-based pipeline composition,
structured error types with sealed interfaces, fail-fast vs
accumulating validation, and a full user-registration example.

Pull Request

📌 Summary

Briefly describe the purpose of this pull request and what problem it solves.

Example: This PR adds a functional implementation of a lazy list, demonstrating deferred computation using Java 17 features.


✅ Checklist

Please check all that apply:

  • I have tested my changes locally
  • I have added unit tests where applicable
  • I have updated documentation where necessary
  • My code follows the project's coding conventions
  • I have linked any related issue(s) below

🔗 Related Issues

Closes #55
Fixes #[issue-number]
(Related but not closing: #[issue-number])


💬 Additional Notes

Any other context, screenshots, design decisions, or points to be reviewed carefully.

Summary by CodeRabbit

  • Documentation
    • Added a comprehensive blog post introducing Railway-Oriented Programming in Java: functional error-handling patterns, Result-based combinators, pipeline examples, error-accumulation approaches, testing guidance, and advice for readable, exception-free domain modeling.
  • Chores
    • Minor site dependency updates and maintenance tweaks.

  Introduce a new article covering the ROP pattern using pure Java:
  two-track Result<T,E> type, flatMap-based pipeline composition,
  structured error types with sealed interfaces, fail-fast vs
  accumulating validation, and a full user-registration example.
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Mar 5, 2026

📝 Walkthrough

Walkthrough

A new blog article introducing Railway-Oriented Programming (ROP) in Java is added, demonstrating error handling using sealed Result<T, E> types with functional combinators, practical pipeline examples, and error handling strategies. Additionally, site dependencies are bumped in site/package.json.

Changes

Cohort / File(s) Summary
Blog Article Addition
site/src/data/blog/railway-oriented-programming-in-java.md
Adds a comprehensive blog post on Railway-Oriented Programming in Java: sealed Result type, smart constructors, combinators (map, flatMap, mapError, fold), pipeline examples (parsing → validation → uniqueness → hashing → persistence), error accumulation patterns, testing notes, and usage guidance.
Site Dependency Bump
site/package.json
Bumps site dependencies: astro ^5.17.1 → ^5.18.0 and astro-expressive-code ^0.41.6 → ^0.41.7. No other script or content changes.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~12 minutes

Poem

🐰 On rails I hop, with code so neat and small,
Two tracks I show — where triumphs rise or fall.
No throws, just types that guide the flow,
FlatMaps lead where clean results go.
Hooray for pipelines, tested, short, and tall! 🛤️✨

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (2 warnings)

Check name Status Explanation Resolution
Linked Issues check ⚠️ Warning The blog post addresses the core requirements from issue #55: explains ROP using Result<T,E>, demonstrates two-track error handling, shows flatMap-based pipeline composition, includes error types with sealed interfaces, and covers validation strategies with a user-registration example. However, the acceptance criterion requiring runnable code snippets extracted from a samples/ subproject is not met. The post should include runnable code snippets extracted from a samples/ subproject rather than inline examples. Ensure code examples can be executed and tested independently.
Out of Scope Changes check ⚠️ Warning The PR includes dependency bumps in site/package.json (astro and astro-expressive-code versions) which are unrelated to the blog post content objective. Remove the dependency version bumps from site/package.json as they are out of scope; those changes should be in a separate maintenance PR.
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The PR title clearly summarizes the main change: adding a blog post about Railway-Oriented Programming in Java, which matches the primary objective of the changeset.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Description check ✅ Passed The PR description includes the required template structure with Summary, Checklist, and Related Issues sections, with issue #55 linked. However, the Summary section duplicates the introductory text rather than following the template's guidance to briefly describe the purpose and problem solved.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feature/blog/post/railway_oriented_programming

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@github-actions
Copy link

github-actions bot commented Mar 5, 2026

Overall Project 99.13% 🍏

There is no coverage information present for the Files changed

@domix domix self-assigned this Mar 5, 2026
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@site/src/data/blog/railway-oriented-programming-in-java.md`:
- Line 357: The snippet calls User.anonymous() but that static factory is not
defined, so either add a clear definition on the User type (e.g., a static
method User.anonymous() returning a default/guest User) or replace the call site
result.getOrElse(User.anonymous()) with an inline fallback instance (e.g.,
result.getOrElse(new User(...)) or result.getOrElse(User.guest()) if you prefer
a different name); update the User class to include the chosen factory name
(anonymous() or guest()) so the example is self-contained and compiles.
- Around line 54-58: The markdown fenced block containing the railway diagram
(the block starting with the lines "input ──[step1]──[step2]──[step3]──▶
Success(result)" and its following lines) lacks a language tag and triggers
MD040; update that fence to include a language hint (e.g., add "text" after the
opening triple backticks: ```text) so the linter recognizes it as a code/diagram
block.
- Around line 276-284: The hashPassword function currently uses
req.password().hashCode() which is unsafe; replace the simplified hashing line
in hashPassword (the creation of the "hashed" variable and its "bcrypt:" prefix)
with a call to a real password-hashing library (e.g., BCrypt/Argon2/PBKDF2) that
produces a salted, slow hash, and return that value in the new
RegistrationRequest; ensure exceptions from the hashing library are caught and
wrapped in RegistrationError.StorageFailure as currently done. If you must keep
a doc-only example, instead add a clear, prominent “never use in production —
example only” warning comment directly above hashPassword and change the
placeholder to explicitly indicate it’s non-functional rather than showing
req.password().hashCode().

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 038d715e-a77f-4867-bb75-bd244e23b747

📥 Commits

Reviewing files that changed from the base of the PR and between b80d917 and 2cd9b1e.

📒 Files selected for processing (1)
  • site/src/data/blog/railway-oriented-programming-in-java.md

Comment on lines +54 to +58
```
input ──[step1]──[step2]──[step3]──▶ Success(result)
└──────────────────▶ Failure(error)
```
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Add a language hint to the railway diagram code fence.

The fenced block is missing a language tag, which triggers markdown linting (MD040).

Suggested fix
-```
+```text
 input ──[step1]──[step2]──[step3]──▶ Success(result)
                │
                └──────────────────▶ Failure(error)
</details>

<!-- suggestion_start -->

<details>
<summary>📝 Committable suggestion</summary>

> ‼️ **IMPORTANT**
> Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

```suggestion

🧰 Tools
🪛 markdownlint-cli2 (0.21.0)

[warning] 54-54: Fenced code blocks should have a language specified

(MD040, fenced-code-language)

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@site/src/data/blog/railway-oriented-programming-in-java.md` around lines 54 -
58, The markdown fenced block containing the railway diagram (the block starting
with the lines "input ──[step1]──[step2]──[step3]──▶ Success(result)" and its
following lines) lacks a language tag and triggers MD040; update that fence to
include a language hint (e.g., add "text" after the opening triple backticks:
```text) so the linter recognizes it as a code/diagram block.

Comment on lines +276 to +284
public static Result<RegistrationRequest, RegistrationError> hashPassword(
RegistrationRequest req
) {
try {
String hashed = "bcrypt:" + req.password().hashCode(); // simplified
return Result.ok(new RegistrationRequest(req.email(), req.name(), hashed));
} catch (Exception e) {
return Result.err(new RegistrationError.StorageFailure("hashing failed: " + e.getMessage()));
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Avoid demonstrating password hashing with hashCode().

Even with “simplified” wording, this is an unsafe pattern that readers may copy into production code. Use a real password-hashing example (BCrypt/Argon2/PBKDF2), or add an explicit “never use in production” warning directly above this line.

Suggested doc-safe adjustment
-    // --- Password hashing (simulated) ---
+    // --- Password hashing (simulated; DO NOT use hashCode for real passwords) ---
 ...
-            String hashed = "bcrypt:" + req.password().hashCode(); // simplified
+            String hashed = "<hashed-password-placeholder>"; // illustrative only
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@site/src/data/blog/railway-oriented-programming-in-java.md` around lines 276
- 284, The hashPassword function currently uses req.password().hashCode() which
is unsafe; replace the simplified hashing line in hashPassword (the creation of
the "hashed" variable and its "bcrypt:" prefix) with a call to a real
password-hashing library (e.g., BCrypt/Argon2/PBKDF2) that produces a salted,
slow hash, and return that value in the new RegistrationRequest; ensure
exceptions from the hashing library are caught and wrapped in
RegistrationError.StorageFailure as currently done. If you must keep a doc-only
example, instead add a clear, prominent “never use in production — example only”
warning comment directly above hashPassword and change the placeholder to
explicitly indicate it’s non-functional rather than showing
req.password().hashCode().

### `getOrElse` — extract with a fallback

```java
User user = result.getOrElse(User.anonymous());
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

User.anonymous() is undefined in the article snippets.

This makes the snippet non-self-contained for readers trying to copy and run it. Either define anonymous() in the User section or switch to an inline fallback instance.

Suggested fix
-User user = result.getOrElse(User.anonymous());
+User user = result.getOrElse(new User(0L, "[email protected]", "Anonymous", ""));
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
User user = result.getOrElse(User.anonymous());
User user = result.getOrElse(new User(0L, "[email protected]", "Anonymous", ""));
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@site/src/data/blog/railway-oriented-programming-in-java.md` at line 357, The
snippet calls User.anonymous() but that static factory is not defined, so either
add a clear definition on the User type (e.g., a static method User.anonymous()
returning a default/guest User) or replace the call site
result.getOrElse(User.anonymous()) with an inline fallback instance (e.g.,
result.getOrElse(new User(...)) or result.getOrElse(User.guest()) if you prefer
a different name); update the User class to include the chosen factory name
(anonymous() or guest()) so the example is self-contained and compiles.

@github-actions
Copy link

github-actions bot commented Mar 5, 2026

Overall Project 99.13% 🍏

There is no coverage information present for the Files changed

@domix domix merged commit f0b705b into main Mar 5, 2026
4 checks passed
@domix domix deleted the feature/blog/post/railway_oriented_programming branch March 5, 2026 04:55
@github-actions
Copy link

github-actions bot commented Mar 5, 2026

Overall Project 99.13% 🍏

There is no coverage information present for the Files changed

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Blog post: Railway-Oriented Programming in Java (Without Frameworks)

1 participant