View Javadoc
1   package com.guinetik.corefun.examples;
2   
3   import com.guinetik.corefun.Loggable;
4   import com.guinetik.corefun.Result;
5   import com.guinetik.corefun.SafeExecutor;
6   
7   /**
8    * Demonstrates usage of SafeExecutor for timed, logged operations.
9    *
10   * SafeExecutor combines timing, logging, and exception handling into
11   * a unified interface. It integrates with Loggable for framework-agnostic
12   * logging, making it easy to plug in SLF4J, Log4j, or any other logger.
13   */
14  public class SafeExecutorExample {
15  
16      public static void main(String[] args) {
17          System.out.println("=== SafeExecutor Examples ===\n");
18  
19          basicUsage();
20          implementingSafeExecutor();
21          safelyResultPattern();
22          customLogging();
23      }
24  
25      /**
26       * Basic usage with factory methods.
27       */
28      static void basicUsage() {
29          System.out.println("--- Basic Usage (println logger) ---");
30  
31          // Create a SafeExecutor with println logging
32          SafeExecutor executor = SafeExecutor.println();
33  
34          // Execute with timing and logging
35          String result = executor.safely("Compute greeting", () -> {
36              Thread.sleep(50); // Simulate work
37              return "Hello, World!";
38          });
39          System.out.println("Result: " + result);
40  
41          // Void operations (using safelySafe for operations that throw)
42          System.out.println("\nVoid operation:");
43          executor.safelySafe("Perform cleanup", () -> {
44              Thread.sleep(30);
45              System.out.println("  [Cleanup work happening...]");
46          });
47  
48          // Silent executor (no logging)
49          System.out.println("\nSilent executor:");
50          SafeExecutor silent = SafeExecutor.noop();
51          String silentResult = silent.safely("No logs", () -> "Done quietly");
52          System.out.println("Silent result: " + silentResult);
53  
54          System.out.println();
55      }
56  
57      /**
58       * Implementing SafeExecutor in your own class.
59       */
60      static void implementingSafeExecutor() {
61          System.out.println("--- Implementing SafeExecutor ---");
62  
63          // Your service class can implement SafeExecutor
64          DataProcessor processor = new DataProcessor();
65          processor.processData("some-data-id");
66  
67          System.out.println();
68      }
69  
70      /**
71       * Using safelyResult for non-throwing operations.
72       */
73      static void safelyResultPattern() {
74          System.out.println("--- safelyResult (No Exceptions) ---");
75  
76          SafeExecutor executor = SafeExecutor.println();
77  
78          // Returns Result instead of throwing
79          Result<Integer, String> success = executor.safelyResult(
80                  "Parse valid number",
81                  () -> Integer.parseInt("42")
82          );
83          System.out.println("Parse result: " + success);
84  
85          Result<Integer, String> failure = executor.safelyResult(
86                  "Parse invalid number",
87                  () -> Integer.parseInt("not-a-number")
88          );
89          System.out.println("Parse failure: " + failure);
90  
91          // Chain with Result operations
92          String message = success
93                  .map(n -> n * 2)
94                  .fold(
95                          error -> "Error: " + error,
96                          value -> "Doubled value: " + value
97                  );
98          System.out.println(message);
99  
100         System.out.println();
101     }
102 
103     /**
104      * Custom logging integration examples.
105      */
106     static void customLogging() {
107         System.out.println("--- Custom Logging ---");
108 
109         // Create a logger with custom formatting
110         Loggable.Logger customLogger = new Loggable.Logger() {
111             @Override
112             public void info(String message) {
113                 System.out.println("📘 " + message);
114             }
115 
116             @Override
117             public void warn(String message) {
118                 System.out.println("⚠️  " + message);
119             }
120 
121             @Override
122             public void error(String message) {
123                 System.err.println("❌ " + message);
124             }
125 
126             @Override
127             public void error(String message, Throwable t) {
128                 System.err.println("❌ " + message + " - " + t.getMessage());
129             }
130         };
131 
132         SafeExecutor customExecutor = SafeExecutor.withLogger(customLogger);
133         customExecutor.safely("Custom logged operation", () -> {
134             Thread.sleep(25);
135             return "done";
136         });
137 
138         // Tagged logger (adds prefix)
139         System.out.println("\nTagged logger:");
140         Loggable.Logger tagged = Loggable.Logger.tagged("DataService",
141                 Loggable.Logger.println());
142         SafeExecutor taggedExecutor = SafeExecutor.withLogger(tagged);
143         taggedExecutor.safely("Tagged operation", () -> "result");
144 
145         // Example: SLF4J integration (pseudo-code)
146         System.out.println("\n// SLF4J integration example:");
147         System.out.println("// private static final org.slf4j.Logger LOG = LoggerFactory.getLogger(MyClass.class);");
148         System.out.println("// Loggable.Logger logger = Loggable.Logger.of(LOG::info, LOG::warn, LOG::error);");
149 
150         System.out.println();
151     }
152 
153     /**
154      * Example service class implementing SafeExecutor.
155      */
156     static class DataProcessor implements SafeExecutor {
157         // In a real app, this would be your SLF4J/Log4j logger
158         private final Loggable.Logger log = Loggable.Logger.tagged("DataProcessor",
159                 Loggable.Logger.println());
160 
161         @Override
162         public Loggable.Logger logger() {
163             return log;
164         }
165 
166         public void processData(String dataId) {
167             // The safely() method is inherited from SafeExecutor
168             Result<String, String> result = safelyResult(
169                     "Process data " + dataId,
170                     () -> {
171                         // Simulate processing
172                         Thread.sleep(75);
173                         return "Processed: " + dataId;
174                     }
175             );
176 
177             result
178                     .peekSuccess(data -> logger().info("Success: " + data))
179                     .peekFailure(error -> logger().error("Failed: " + error));
180         }
181     }
182 }