A combination of the Try monad and the Either monad, to help tame complex business flows
Example Usage 1 (thanks @tjheslin1)
Example Usage 2 (thanks @hanfak)
A small Java 8 library that can help you to model a 3-part (happy/sad/exception) business flow. No more try-catch blocks if you don't want to use them!
If you have a flow that fits into the "two track" model, as spoken about by Scott W in his Railyway Oriented Programming model, which this library owes a lot to. This library has 3 tracks instead of 2; the third is supposed to be reserved for "stuff that is never supposed to happen" in the form of uncaught exceptions.
There is no point in using this if your flows are "all or nothing". If there are no expected sad paths and all failures are exceptional circumstances, then this is not a good fit. The Try monad is a better fit. You could use e.g. better-java-monads instead.
<dependency>
<groupId>io.github.theangrydev</groupId>
<artifactId>business-flows</artifactId>
<version>10.3.0</version>
</dependency>
The versioning scheme follows Semantic Versioning 2.0.0, to help you identify non backwards-compatible changes when you are upgrading.
- Added
BusinessFlow.isTechnicalFailure
method to complement the existingisHappy
andisSad
methods - Added
BusinessFlow.getTechnicalFailure
method to complement the existinggetHappy
andgetSad
methods
- Starting to document the API with some new annotations
@ApiFeature
, which describesApiFeatureStability
for a version in theApiVersionHistory
. These features are EXPERIMENTAL and may be removed at any time
- Experimenting with the release process and generating documentation, no functional changes
HappyPath.happyPathAttempt
now accepts anyBusinessFlow
, not just aHappyPath
, which is useful when you have a collaborator that returns aBusinessFlow
that is not aHappyPath
view (closes #13)
- This release picks up where 8.3.0 left off, just reverting the version 9.0.0 and 9.1.0 changes
- These releases were a failed attempt to remove the
HappyPath.happyAttempt
method that takes anAttempt<Happy>
parameter (see #12)
- Add methods
consume
andconsumeOrThrow
to end a flow by performing some action that ends in a void (closes #8)
- Add methods to help with multiple return style:
isHappy
,isSad
,getHappy
andgetSad
(closes #10)
throwItAsARuntimeException
andthrowIt
should not be void (closes #5)
- Removed the
Bias
parameter fromBusinessFlow
to make it more viable to use as an unbiased return type, instead of having to wildcard the types as<Happy, Sad, ?>
. This is a breaking change. - Made the
then
methods accept? extends BusinessFlow
.
- Exposed some methods on
PotentialFailure
to make it easier to test when it is the return type of a method. This involved extracting aWithOptional
interface that is used byPotentialFailure
andBusinessFlow
.
- Added helper method
HappyPath.actions
that turns an array ofActionThatMightFail
into a list. This is a workaround for the fact that interfaces can't have@SafeVarargs
and so some methods accept a list when they would ideally accept varargs
- Added
HappyPath.attemptAll
convenience method that is equivalent to multiple chainedattempt
calls
- Added method
TechnicalFailure.throwItAsRuntimeException
that will throw aRuntimeException
if the business case is a technical failure
- Added method
TechnicalFailure.throwIt
that will throw anException
if the business case is a technical failure
- Changed
Validator
so that it produces just one failure not a list of failures FieldValidator
now adapts just oneValidator
not a list of them to match theValidator
change- Renamed
ValidationPath
methods fromvalidate*
tovalidateAll*
to make it clear that they run all the validators not just until the first failure
TechnicalFailureCase.toString
now includes the stack trace
- Added method
BusinessCase.toPotentialFalure
that turns aBusinessCase
into aPotentialFailure
ValidationPath
now has aSadAggregate
type parameter that defaults toList<Sad>
and can be used to map validation errors into an aggregate. ValidationPath now has a SadAggregate type parameter that defaults to List and can be used to map validation errors into an aggregate. There are correspondingvalidateInto
methods inValidationPath
that allow specifying aMapping
to aSadAggregate
andvalidate
methods that default toList<Sad>
. This change is not backwards compatible
- Helper methods for
FieldValidator
to cope with the case that a common field name should be passed to validators so they can use the name in the validation message
- Validation revamp. Helper
FieldValidator
for field validation, a newValidator
type,PotentialFailure.failures
helper method andValidationPath
helper methods. This change is not backwards compatible
- Updated javadoc and license headers
- Inline methods to make debugging easier (closes #1)
- Removed varargs methods from
ValidationPath
. This change is not backwards compatible - Removed
andThen
methods fromAttempt
andMapping
. This change is not backwards compatible
- Optimized overrides for
ifHappy
etc (closes #2)
- Allow
? extends ActionThatMightFail<Happy, Sad>
in theValidationPath
- Made
PotentialFailure.toHappyPath
package private since it is only supposed to be used internally
- License headers updated
- Using a new class
PotentialFailure
to represent the result of anActionThatMightFail
instead of anOptional
. This change is not backwards compatible
- Updated javadoc
- If a technical failure occurs while joining to happy or sad, it is joined to a technical failure instead
- Unchecked version of
join
with only happy and sad joiners has taken thejoin
name. The checked version is calledjoinOrThrow
now
- Recovery methods no longer need to be e.g.
exception -> sad
, they can choose to ignore the parameter and just supply a value, e.g.() -> sad
- Added
HappyPath.happyPathAttempt
to cover the case where the entry point to a flow is a method that could e.g. return eitherHappyPath.happyPath
orSadPath.sadPath
and may also throw an uncaught exception
- Made all the static factory methods for
HappyPath
,SadPath
andTechnicalFailure
public so that it is possible to do e.g.HappyPath.sadPath(sad)
to get a happy biased view of a sad path without having to doSadPath.sadPath(sad).ifHappy()
- Updated javadoc
HappyAttempt
now has an exception to technical failure factory method and an exception to sad path factory method
- Switched order from
<Sad, Happy>
to<Happy, Sad>
because it is more intuitive to users. This change is not backwards compatible
- Added another
join
method in which you can omit the technical failure mapping and allow it to be thrown as anException
- Reduced visibility of methods that should have been
private
- Changed
orElseThrow
so that it throwsX extends Exception
rather thanX extends Throwable
- Changed
get
failure message wording
- Initial stab at Business Flows