11package io .quarkus .arc ;
22
3+ import java .lang .StackWalker .StackFrame ;
34import java .util .concurrent .ExecutorService ;
45import java .util .concurrent .atomic .AtomicReference ;
6+ import java .util .stream .Collectors ;
7+ import java .util .stream .Stream ;
8+
9+ import org .jboss .logging .Logger ;
510
611import io .quarkus .arc .impl .ArcContainerImpl ;
712
@@ -12,6 +17,16 @@ public final class Arc {
1217
1318 private static final AtomicReference <ArcContainerImpl > INSTANCE = new AtomicReference <>();
1419
20+ /**
21+ * If this system property is set then log a warning with diagnostic information when {@link Arc#container()} returns
22+ * {@code null}.
23+ *
24+ * @see #container()
25+ */
26+ private static final String LOG_NO_CONTAINER = "quarkus.arc.log-no-container" ;
27+
28+ private static final Logger LOG = Logger .getLogger (Arc .class );
29+
1530 /**
1631 * Initializes {@link ArcContainer} with default settings.
1732 * This is equal to using {@code Arc#initialize(ArcInitConfig.INSTANCE)}
@@ -46,15 +61,35 @@ public static ArcContainer initialize(ArcInitConfig config) {
4661 }
4762
4863 public static void setExecutor (ExecutorService executor ) {
49- INSTANCE .get ().setExecutor (executor );
64+ ArcContainerImpl container = INSTANCE .get ();
65+ if (container == null ) {
66+ throw containerNotInitialized ();
67+ }
68+ container .setExecutor (executor );
5069 }
5170
5271 /**
5372 *
54- * @return the container instance
73+ * @return the container instance or {@code null} if the container is not initialized
5574 */
5675 public static ArcContainer container () {
57- return INSTANCE .get ();
76+ ArcContainer container = INSTANCE .get ();
77+ if (container == null && System .getProperty (LOG_NO_CONTAINER ) != null ) {
78+ LOG .warn (gatherDiagnosticInfo ());
79+ }
80+ return container ;
81+ }
82+
83+ /**
84+ * @return the container instance
85+ * @throws IllegalStateException if the container is not initialized
86+ */
87+ public static ArcContainer requireContainer () {
88+ ArcContainer container = INSTANCE .get ();
89+ if (container == null ) {
90+ throw containerNotInitialized ();
91+ }
92+ return container ;
5893 }
5994
6095 public static void shutdown () {
@@ -70,4 +105,38 @@ public static void shutdown() {
70105 }
71106 }
72107
108+ private static IllegalStateException containerNotInitialized () {
109+ String msg = "ArC container not initialized: the container is not started, already shut down, or a wrong class loader was used to load the io.quarkus.arc.Arc class\n "
110+ + "\t - CL: %s\n "
111+ + "\t - TCCL: %s" ;
112+ ClassLoader tccl = Thread .currentThread ().getContextClassLoader ();
113+ ClassLoader cl = Arc .class .getClassLoader ();
114+ return new IllegalStateException (msg .formatted (cl , tccl ));
115+ }
116+
117+ private static String gatherDiagnosticInfo () {
118+ ClassLoader tccl = Thread .currentThread ().getContextClassLoader ();
119+ ClassLoader cl = Arc .class .getClassLoader ();
120+ String msg = "\n "
121+ + "==============================\n "
122+ + "ArC: container not initialized\n "
123+ + "------------------------------\n "
124+ + "The container is not started, already shut down, or a wrong class loader was used to load the io.quarkus.arc.Arc class.\n "
125+ + "\n "
126+ + "CL: %1$s\n "
127+ + "TCCL: %2$s\n "
128+ + "Stack:\n \t %3$s"
129+ + "\n "
130+ + "===================================\n " ;
131+ StackWalker walker = StackWalker .getInstance ();
132+ return msg .formatted (cl , tccl , walker .walk (Arc ::collectStack ));
133+ }
134+
135+ private static String collectStack (Stream <StackFrame > stream ) {
136+ return stream
137+ .skip (1 )
138+ .map (Object ::toString )
139+ .collect (Collectors .joining ("\n \t " ));
140+ }
141+
73142}
0 commit comments