Skip to content

Commit acaecb4

Browse files
committed
Usage POC for SafeFunction
1 parent b04865f commit acaecb4

File tree

1 file changed

+189
-0
lines changed

1 file changed

+189
-0
lines changed
Lines changed: 189 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,189 @@
1+
package test.org.fugerit.java.core.function;
2+
3+
import lombok.extern.slf4j.Slf4j;
4+
import org.fugerit.java.core.cfg.ConfigRuntimeException;
5+
import org.fugerit.java.core.function.SafeFunction;
6+
import org.fugerit.java.core.function.UnsafeVoid;
7+
import org.junit.Assert;
8+
import org.junit.Test;
9+
10+
import java.io.IOException;
11+
import java.util.function.Consumer;
12+
import java.util.function.Function;
13+
14+
/*
15+
* Abstract : this test class shows why and how to use the method in utility class:
16+
*
17+
* org.fugerit.java.core.function.SafeFunction
18+
*
19+
* the goal is to compare SafeFunction usage with classical "try { ... } catch ( ... ) {} approach.
20+
*
21+
* When using try catch, many times two simple patterns are applied
22+
*
23+
* error logging :
24+
try {
25+
[...]
26+
} catch (Exception e) {
27+
log.error( .... );
28+
}
29+
*
30+
* or :
31+
*
32+
* error rethrow :
33+
try {
34+
[...]
35+
} catch (Exception e) {
36+
throw new CustomException( e ); // often a runtime exception
37+
}
38+
*
39+
* SafeFunction utility uses lambdas to help handle this situation in a standard way.
40+
*
41+
* Main benefits are :
42+
* - standardized exception handling
43+
* - try section and catch section can be tested separately
44+
* (for instance in unit test, where sometimes it's hard to reproduce the error condition)
45+
*
46+
* Some drawbacks could be :
47+
* - the code and stack traces maybe more difficult to read as coders are not used to it
48+
* - if not customized, default behaviour is to always use a wrapping exception :
49+
* org.fugerit.java.core.cfg.ConfigRuntimeException
50+
*
51+
* NOTE: if a custom exception handling is needed, it is possible to either :
52+
* - provide a custom exception handling to SafeFunction
53+
* - revert to standard try / catch approach
54+
*
55+
* here is the javadoc :
56+
* https://javadoc.io/doc/org.fugerit.java/fj-core/latest/org/fugerit/java/core/function/SafeFunction.html
57+
*
58+
* and here the source code :
59+
* https://javadoc.io/doc/org.fugerit.java/fj-core/latest/org/fugerit/java/core/function/SafeFunction.html
60+
*
61+
* going further :
62+
* a few other options are provided rethrowing custom non-runtime exceptions, for instance :
63+
* - org.fugerit.java.core.io.helper.HelperIOException
64+
* - org.fugerit.java.core.db.dao.DAOException
65+
* - org.fugerit.java.core.xml.XMLException
66+
*
67+
*/
68+
@Slf4j
69+
public class TestPOCSafeFunction {
70+
71+
/*
72+
* simple function to use as the body of this class's scenarios
73+
*
74+
* it always throws a java.io.IOException
75+
*/
76+
private static final UnsafeVoid<Exception> SCENARIO = () -> {
77+
if ( Boolean.TRUE ) {
78+
throw new IOException( "My scenario exception" );
79+
}
80+
};
81+
82+
/*
83+
* simple custom exception handler.
84+
*
85+
* if the exception is a java.io.IOException it will only log the message
86+
* otherwise it will log both message and stack trace
87+
*
88+
* log level will be 'warning' anyway.
89+
*
90+
*/
91+
private static final Consumer<Exception> CUSTOM_EXCEPTION_HANDLER = e -> {
92+
if ( e instanceof IOException ) {
93+
SafeFunction.EX_CONSUMER_LOG_WARN.accept( e );
94+
} else {
95+
SafeFunction.EX_CONSUMER_TRACE_WARN.accept( e );
96+
}
97+
};
98+
99+
public void applyTryCatch() {
100+
try {
101+
SCENARIO.apply();
102+
} catch (Exception e) {
103+
throw new ConfigRuntimeException( e );
104+
}
105+
}
106+
107+
public void applySafeFunction() {
108+
SafeFunction.apply( SCENARIO::apply );
109+
}
110+
111+
/*
112+
* In this POC, a piece of code (SCENARIO:apply) is called both in :
113+
* - try catch mode
114+
* - SafeFunction.apply() mode.
115+
* And a org.fugerit.java.core.cfg.ConfigRuntimeException is checked to be thrown.
116+
*/
117+
@Test
118+
public void testSafeFunctionApply() {
119+
// classical try catch
120+
Assert.assertThrows( ConfigRuntimeException.class, this::applyTryCatch );
121+
// safe function
122+
Assert.assertThrows( ConfigRuntimeException.class, this::applySafeFunction );
123+
}
124+
125+
public boolean getTryCatch() {
126+
try {
127+
SCENARIO.apply();
128+
return Boolean.TRUE;
129+
} catch (Exception e) {
130+
throw new ConfigRuntimeException( e );
131+
}
132+
}
133+
134+
public boolean getSafeFunction() {
135+
SafeFunction.apply( SCENARIO::apply );
136+
return Boolean.TRUE;
137+
}
138+
139+
/*
140+
* In this POC, a piece of code (SCENARIO:apply) is called both in :
141+
* - try catch mode
142+
* - SafeFunction.get() mode.
143+
* And a org.fugerit.java.core.cfg.ConfigRuntimeException is checked to be thrown.
144+
*/
145+
@Test
146+
public void testSafeFunctionGet() {
147+
// classical try catch
148+
Assert.assertThrows( ConfigRuntimeException.class, this::getTryCatch );
149+
// safe function
150+
Assert.assertThrows( ConfigRuntimeException.class, this::getSafeFunction );
151+
}
152+
153+
/*
154+
* In this POC, a piece of code (SCENARIO:apply) is called both in :
155+
* - try catch mode
156+
* - SafeFunction.apply() mode.
157+
* And the thrown IO Exception is just logged with no further handling
158+
*/
159+
@Test
160+
public void testSafeFunctionApplySilent() {
161+
// classical try catch
162+
try {
163+
SCENARIO.apply();
164+
} catch (Exception e) {
165+
log.warn( "Exception suppressed : {}", e.toString() );
166+
}
167+
// safe function
168+
SafeFunction.applySilent( SCENARIO::apply );
169+
}
170+
171+
/*
172+
* In this POC, a piece of code (SCENARIO:apply) is called both in :
173+
* - try catch mode
174+
* - SafeFunction.apply() mode.
175+
* And a custom exception handling is applied.
176+
*/
177+
@Test
178+
public void testSafeFunctionApplyCustomHandling() {
179+
// classical try catch
180+
try {
181+
SCENARIO.apply();
182+
} catch (Exception e) {
183+
CUSTOM_EXCEPTION_HANDLER.accept( e );
184+
}
185+
// safe function
186+
SafeFunction.apply( SCENARIO::apply, CUSTOM_EXCEPTION_HANDLER );
187+
}
188+
189+
}

0 commit comments

Comments
 (0)