This is an automated email from the ASF dual-hosted git repository.

jamesbognar pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/juneau.git


The following commit(s) were added to refs/heads/master by this push:
     new dfa8bb664c juneau-marshall improvements
dfa8bb664c is described below

commit dfa8bb664c9c8be8e0bac384d15bdb33dccea854
Author: James Bognar <[email protected]>
AuthorDate: Wed Dec 17 13:09:47 2025 -0500

    juneau-marshall improvements
---
 .../main/java/org/apache/juneau/BeanContext.java   | 13 ++++---
 .../org/apache/juneau/html/HtmlDocSerializer.java  | 14 +++++---
 .../org/apache/juneau/html/HtmlSerializer.java     | 14 +++++---
 .../org/apache/juneau/json/JsonSerializer.java     | 14 +++++---
 .../org/apache/juneau/rest/client/RestClient.java  | 41 +++++++++++++---------
 .../apache/juneau/rest/stats/MethodExecStats.java  | 19 +++++++---
 6 files changed, 78 insertions(+), 37 deletions(-)

diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/BeanContext.java 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/BeanContext.java
index 982b41b103..dfde27e167 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/BeanContext.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/BeanContext.java
@@ -31,6 +31,7 @@ import java.lang.annotation.*;
 import java.lang.reflect.*;
 import java.util.*;
 import java.util.concurrent.*;
+import java.util.concurrent.atomic.*;
 import java.util.stream.*;
 
 import org.apache.juneau.annotation.*;
@@ -3590,7 +3591,7 @@ public class BeanContext extends Context {
        private final BeanRegistry beanRegistry;
        private final BeanSession defaultSession;
        private final PropertyNamer propertyNamerBean;
-       private volatile WriterSerializer beanToStringSerializer;
+       private final AtomicReference<WriterSerializer> beanToStringSerializer 
= new AtomicReference<>();
 
        /**
         * Constructor.
@@ -4221,12 +4222,16 @@ public class BeanContext extends Context {
         * @return The serializer.  May be <jk>null</jk> if all initialization 
has occurred.
         */
        protected WriterSerializer getBeanToStringSerializer() {
-               if (beanToStringSerializer == null) {
+               WriterSerializer result = beanToStringSerializer.get();
+               if (result == null) {
                        if (JsonSerializer.DEFAULT == null)
                                return null;
-                       this.beanToStringSerializer = 
JsonSerializer.create().beanContext(this).sq().simpleAttrs().build();
+                       result = 
JsonSerializer.create().beanContext(this).sq().simpleAttrs().build();
+                       if (! beanToStringSerializer.compareAndSet(null, 
result)) {
+                               result = beanToStringSerializer.get();
+                       }
                }
-               return beanToStringSerializer;
+               return result;
        }
 
        /**
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/html/HtmlDocSerializer.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/html/HtmlDocSerializer.java
index 3d66197ee4..29c2570b4b 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/html/HtmlDocSerializer.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/html/HtmlDocSerializer.java
@@ -23,6 +23,7 @@ import static org.apache.juneau.commons.utils.Utils.*;
 import java.lang.annotation.*;
 import java.nio.charset.*;
 import java.util.*;
+import java.util.concurrent.atomic.*;
 import java.util.function.*;
 import java.util.regex.*;
 
@@ -1640,7 +1641,7 @@ public class HtmlDocSerializer extends 
HtmlStrippedDocSerializer {
        private final HtmlWidget[] widgetArray;
        private final HtmlDocTemplate templateBean;
 
-       private volatile HtmlSchemaDocSerializer schemaSerializer;
+       private final AtomicReference<HtmlSchemaDocSerializer> schemaSerializer 
= new AtomicReference<>();
 
        /**
         * Constructor.
@@ -1683,9 +1684,14 @@ public class HtmlDocSerializer extends 
HtmlStrippedDocSerializer {
 
        @Override /* Overridden from XmlSerializer */
        public HtmlSerializer getSchemaSerializer() {
-               if (schemaSerializer == null)
-                       schemaSerializer = 
HtmlSchemaDocSerializer.create().beanContext(getBeanContext()).build();
-               return schemaSerializer;
+               HtmlSchemaDocSerializer result = schemaSerializer.get();
+               if (result == null) {
+                       result = 
HtmlSchemaDocSerializer.create().beanContext(getBeanContext()).build();
+                       if (! schemaSerializer.compareAndSet(null, result)) {
+                               result = schemaSerializer.get();
+                       }
+               }
+               return result;
        }
 
        @Override /* Overridden from Context */
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/html/HtmlSerializer.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/html/HtmlSerializer.java
index 02d5402d90..887f46cfeb 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/html/HtmlSerializer.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/html/HtmlSerializer.java
@@ -23,6 +23,7 @@ import java.lang.annotation.*;
 import java.nio.charset.*;
 import java.util.*;
 import java.util.concurrent.*;
+import java.util.concurrent.atomic.*;
 
 import org.apache.juneau.*;
 import org.apache.juneau.commons.collections.*;
@@ -1440,7 +1441,7 @@ public class HtmlSerializer extends XmlSerializer 
implements HtmlMetaProvider {
        private final Map<ClassMeta<?>,HtmlClassMeta> htmlClassMetas = new 
ConcurrentHashMap<>();
        private final Map<BeanPropertyMeta,HtmlBeanPropertyMeta> 
htmlBeanPropertyMetas = new ConcurrentHashMap<>();
 
-       private volatile HtmlSchemaSerializer schemaSerializer;
+       private final AtomicReference<HtmlSchemaSerializer> schemaSerializer = 
new AtomicReference<>();
 
        /**
         * Constructor.
@@ -1495,9 +1496,14 @@ public class HtmlSerializer extends XmlSerializer 
implements HtmlMetaProvider {
         * @return The schema serializer.
         */
        public HtmlSerializer getSchemaSerializer() {
-               if (schemaSerializer == null)
-                       schemaSerializer = 
HtmlSchemaSerializer.create().beanContext(getBeanContext()).build();
-               return schemaSerializer;
+               HtmlSchemaSerializer result = schemaSerializer.get();
+               if (result == null) {
+                       result = 
HtmlSchemaSerializer.create().beanContext(getBeanContext()).build();
+                       if (! schemaSerializer.compareAndSet(null, result)) {
+                               result = schemaSerializer.get();
+                       }
+               }
+               return result;
        }
 
        @Override /* Overridden from Context */
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/json/JsonSerializer.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/json/JsonSerializer.java
index ef15cb046d..9a0615340d 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/json/JsonSerializer.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/json/JsonSerializer.java
@@ -23,6 +23,7 @@ import java.lang.annotation.*;
 import java.nio.charset.*;
 import java.util.*;
 import java.util.concurrent.*;
+import java.util.concurrent.atomic.*;
 
 import org.apache.juneau.*;
 import org.apache.juneau.commons.collections.*;
@@ -1047,7 +1048,7 @@ public class JsonSerializer extends WriterSerializer 
implements JsonMetaProvider
        private final Map<BeanPropertyMeta,JsonBeanPropertyMeta> 
jsonBeanPropertyMetas = new ConcurrentHashMap<>();
        private final Map<ClassMeta<?>,JsonClassMeta> jsonClassMetas = new 
ConcurrentHashMap<>();
 
-       private volatile JsonSchemaSerializer schemaSerializer;
+       private final AtomicReference<JsonSchemaSerializer> schemaSerializer = 
new AtomicReference<>();
 
        /**
         * Constructor.
@@ -1105,9 +1106,14 @@ public class JsonSerializer extends WriterSerializer 
implements JsonMetaProvider
         * @return The schema serializer.
         */
        public JsonSchemaSerializer getSchemaSerializer() {
-               if (schemaSerializer == null)
-                       schemaSerializer = 
JsonSchemaSerializer.create().beanContext(getBeanContext()).build();
-               return schemaSerializer;
+               JsonSchemaSerializer result = schemaSerializer.get();
+               if (result == null) {
+                       result = 
JsonSchemaSerializer.create().beanContext(getBeanContext()).build();
+                       if (! schemaSerializer.compareAndSet(null, result)) {
+                               result = schemaSerializer.get();
+                       }
+               }
+               return result;
        }
 
        @Override /* Overridden from Context */
diff --git 
a/juneau-rest/juneau-rest-client/src/main/java/org/apache/juneau/rest/client/RestClient.java
 
b/juneau-rest/juneau-rest-client/src/main/java/org/apache/juneau/rest/client/RestClient.java
index 4803413635..ed95b037f8 100644
--- 
a/juneau-rest/juneau-rest-client/src/main/java/org/apache/juneau/rest/client/RestClient.java
+++ 
b/juneau-rest/juneau-rest-client/src/main/java/org/apache/juneau/rest/client/RestClient.java
@@ -40,6 +40,7 @@ import java.nio.charset.*;
 import java.text.*;
 import java.util.*;
 import java.util.concurrent.*;
+import java.util.concurrent.atomic.*;
 import java.util.function.*;
 import java.util.logging.*;
 import java.util.regex.*;
@@ -6191,8 +6192,8 @@ public class RestClient extends BeanContextable 
implements HttpClient, Closeable
        private final String rootUrl;
        private final boolean executorServiceShutdownOnClose;
        private final boolean logToConsole;
-       private volatile boolean isClosed = false;
-       private volatile ExecutorService executorService;
+       private final AtomicBoolean isClosed = new AtomicBoolean(false);
+       private final AtomicReference<ExecutorService> executorService = new 
AtomicReference<>();
 
        /**
         * Constructor.
@@ -6217,7 +6218,8 @@ public class RestClient extends BeanContextable 
implements HttpClient, Closeable
                errorCodes = builder.errorCodes;
                connectionManager = builder.connectionManager;
                console = nn(builder.console) ? builder.console : System.err;
-               executorService = builder.executorService;
+               if (builder.executorService != null)
+                       executorService.set(builder.executorService);
                executorServiceShutdownOnClose = 
builder.executorServiceShutdownOnClose;
                ignoreErrors = builder.ignoreErrors;
                keepHttpClientOpen = builder.keepHttpClientOpen;
@@ -6340,11 +6342,12 @@ public class RestClient extends BeanContextable 
implements HttpClient, Closeable
         */
        @Override
        public void close() throws IOException {
-               isClosed = true;
+               isClosed.set(true);
+               ExecutorService es = executorService.get();
                if (! keepHttpClientOpen)
                        httpClient.close();
-               if (nn(executorService) && executorServiceShutdownOnClose)
-                       executorService.shutdown();
+               if (nn(es) && executorServiceShutdownOnClose)
+                       es.shutdown();
                if (nn(creationStack))
                        closedStack = Thread.currentThread().getStackTrace();
        }
@@ -6353,12 +6356,13 @@ public class RestClient extends BeanContextable 
implements HttpClient, Closeable
         * Same as {@link #close()}, but ignores any exceptions.
         */
        public void closeQuietly() {
-               isClosed = true;
+               isClosed.set(true);
                try {
                        if (! keepHttpClientOpen)
                                httpClient.close();
-                       if (nn(executorService) && 
executorServiceShutdownOnClose)
-                               executorService.shutdown();
+                       ExecutorService es = executorService.get();
+                       if (nn(es) && executorServiceShutdownOnClose)
+                               es.shutdown();
                } catch (@SuppressWarnings("unused") Throwable t) {}
                if (nn(creationStack))
                        closedStack = Thread.currentThread().getStackTrace();
@@ -7697,7 +7701,7 @@ public class RestClient extends BeanContextable 
implements HttpClient, Closeable
 
        @Override
        protected void finalize() throws Throwable {
-               if (detectLeaks && ! isClosed && ! keepHttpClientOpen) {
+               if (detectLeaks && ! isClosed.get() && ! keepHttpClientOpen) {
                        var sb = new StringBuilder("WARNING:  RestClient 
garbage collected before it was finalized.");  // NOT DEBUG
                        if (nn(creationStack)) {
                                sb.append("\nCreation Stack:");  // NOT DEBUG
@@ -7895,7 +7899,7 @@ public class RestClient extends BeanContextable 
implements HttpClient, Closeable
        protected FluentMap<String,Object> properties() {
                return super.properties()
                        .a("errorCodes", errorCodes)
-                       .a("executorService", executorService)
+                       .a("executorService", executorService.get())
                        .a("executorServiceShutdownOnClose", 
executorServiceShutdownOnClose)
                        .a("headerData", headerData)
                        .a("interceptors", interceptors)
@@ -7920,7 +7924,7 @@ public class RestClient extends BeanContextable 
implements HttpClient, Closeable
         * @throws RestCallException If any authentication errors occurred.
         */
        protected RestRequest request(RestOperation op) throws 
RestCallException {
-               if (isClosed) {
+               if (isClosed.get()) {
                        var e2 = (Exception)null;
                        if (nn(closedStack)) {
                                e2 = new Exception("Creation stack:");
@@ -8017,11 +8021,16 @@ public class RestClient extends BeanContextable 
implements HttpClient, Closeable
        }
 
        ExecutorService getExecutorService() {
-               if (nn(executorService))
-                       return executorService;
+               ExecutorService result = executorService.get();
+               if (nn(result))
+                       return result;
                synchronized (this) {
-                       executorService = new ThreadPoolExecutor(1, 1, 30, 
TimeUnit.SECONDS, new ArrayBlockingQueue<>(10));
-                       return executorService;
+                       result = executorService.get();
+                       if (nn(result))
+                               return result;
+                       result = new ThreadPoolExecutor(1, 1, 30, 
TimeUnit.SECONDS, new ArrayBlockingQueue<>(10));
+                       executorService.set(result);
+                       return result;
                }
        }
 
diff --git 
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/stats/MethodExecStats.java
 
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/stats/MethodExecStats.java
index 8160fef02b..3ee8d7f2d8 100644
--- 
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/stats/MethodExecStats.java
+++ 
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/stats/MethodExecStats.java
@@ -108,7 +108,8 @@ public class MethodExecStats {
        private final Method method;
        private final ThrownStore thrownStore;
 
-       private volatile int minTime = -1, maxTime;
+       private final AtomicInteger maxTime = new AtomicInteger();
+       private final AtomicInteger minTime = new AtomicInteger(-1);
 
        private AtomicInteger starts = new AtomicInteger(), finishes = new 
AtomicInteger(), errors = new AtomicInteger();
 
@@ -147,8 +148,13 @@ public class MethodExecStats {
                finishes.incrementAndGet();
                int milliTime = (int)(nanoTime / 1_000_000);
                totalTime.addAndGet(nanoTime);
-               minTime = minTime == -1 ? milliTime : Math.min(minTime, 
milliTime);
-               maxTime = Math.max(maxTime, milliTime);
+               int currentMin = minTime.get();
+               if (currentMin == -1) {
+                       minTime.compareAndSet(-1, milliTime);
+               } else {
+                       minTime.updateAndGet(x -> Math.min(x, milliTime));
+               }
+               maxTime.updateAndGet(x -> Math.max(x, milliTime));
                return this;
        }
 
@@ -186,7 +192,7 @@ public class MethodExecStats {
         *
         * @return The average execution time in milliseconds.
         */
-       public int getMaxTime() { return maxTime; }
+       public int getMaxTime() { return maxTime.get(); }
 
        /**
         * Returns the method name of these stats.
@@ -200,7 +206,10 @@ public class MethodExecStats {
         *
         * @return The average execution time in milliseconds.
         */
-       public int getMinTime() { return minTime == -1 ? 0 : minTime; }
+       public int getMinTime() { 
+               int value = minTime.get();
+               return value == -1 ? 0 : value;
+       }
 
        /**
         * Returns the number currently running method invocations.

Reply via email to