Release MessageBodyWorkers when Response gets closed. (#5039)

Signed-off-by: jansupol <jan.supol@oracle.com>
diff --git a/core-common/src/main/java/org/glassfish/jersey/message/internal/InboundMessageContext.java b/core-common/src/main/java/org/glassfish/jersey/message/internal/InboundMessageContext.java
index 70b1805..81b9f76 100644
--- a/core-common/src/main/java/org/glassfish/jersey/message/internal/InboundMessageContext.java
+++ b/core-common/src/main/java/org/glassfish/jersey/message/internal/InboundMessageContext.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2020 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2022 Oracle and/or its affiliates. All rights reserved.
  *
  * This program and the accompanying materials are made available under the
  * terms of the Eclipse Public License v. 2.0, which is available at
@@ -754,6 +754,9 @@
      * @return context message body workers.
      */
     public MessageBodyWorkers getWorkers() {
+        if (workers == null) {
+            throw new ProcessingException(LocalizationMessages.RESPONSE_CLOSED());
+        }
         return workers;
     }
 
@@ -948,6 +951,7 @@
      */
     public void close() {
         entityContent.close(true);
+        setWorkers(null);
     }
 
     /**
diff --git a/core-server/src/main/java/org/glassfish/jersey/server/ContainerResponse.java b/core-server/src/main/java/org/glassfish/jersey/server/ContainerResponse.java
index 36af408..5e0a1e8 100644
--- a/core-server/src/main/java/org/glassfish/jersey/server/ContainerResponse.java
+++ b/core-server/src/main/java/org/glassfish/jersey/server/ContainerResponse.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2019 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2022 Oracle and/or its affiliates. All rights reserved.
  *
  * This program and the accompanying materials are made available under the
  * terms of the Eclipse Public License v. 2.0, which is available at
@@ -388,6 +388,7 @@
             closed = true;
             messageContext.close();
             requestContext.getResponseWriter().commit();
+            requestContext.setWorkers(null);
         }
     }
 
diff --git a/core-server/src/test/java/org/glassfish/jersey/server/RequestContextBuilder.java b/core-server/src/test/java/org/glassfish/jersey/server/RequestContextBuilder.java
index 6f4a38a..9687a61 100644
--- a/core-server/src/test/java/org/glassfish/jersey/server/RequestContextBuilder.java
+++ b/core-server/src/test/java/org/glassfish/jersey/server/RequestContextBuilder.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2019 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2022 Oracle and/or its affiliates. All rights reserved.
  *
  * This program and the accompanying materials are made available under the
  * terms of the Eclipse Public License v. 2.0, which is available at
@@ -79,31 +79,33 @@
         public void setWorkers(final MessageBodyWorkers workers) {
             super.setWorkers(workers);
             final byte[] entityBytes;
-            if (entity != null) {
-                final MultivaluedMap<String, Object> myMap = new MultivaluedHashMap<String, Object>(getHeaders());
-                final ByteArrayOutputStream baos = new ByteArrayOutputStream();
-                OutputStream stream = null;
-                try {
-                    stream = workers.writeTo(entity, entity.getClass(), entityType.getType(),
-                            new Annotation[0], getMediaType(),
-                            myMap,
-                            propertiesDelegate, baos, Collections.<WriterInterceptor>emptyList());
-                } catch (final IOException | WebApplicationException ex) {
-                    Logger.getLogger(TestContainerRequest.class.getName()).log(Level.SEVERE, null, ex);
-                } finally {
-                    if (stream != null) {
-                        try {
-                            stream.close();
-                        } catch (final IOException e) {
-                            // ignore
+            if (workers != null) {
+                if (entity != null) {
+                    final MultivaluedMap<String, Object> myMap = new MultivaluedHashMap<String, Object>(getHeaders());
+                    final ByteArrayOutputStream baos = new ByteArrayOutputStream();
+                    OutputStream stream = null;
+                    try {
+                        stream = workers.writeTo(entity, entity.getClass(), entityType.getType(),
+                                new Annotation[0], getMediaType(),
+                                myMap,
+                                propertiesDelegate, baos, Collections.<WriterInterceptor>emptyList());
+                    } catch (final IOException | WebApplicationException ex) {
+                        Logger.getLogger(TestContainerRequest.class.getName()).log(Level.SEVERE, null, ex);
+                    } finally {
+                        if (stream != null) {
+                            try {
+                                stream.close();
+                            } catch (final IOException e) {
+                                // ignore
+                            }
                         }
                     }
+                    entityBytes = baos.toByteArray();
+                } else {
+                    entityBytes = new byte[0];
                 }
-                entityBytes = baos.toByteArray();
-            } else {
-                entityBytes = new byte[0];
+                setEntityStream(new ByteArrayInputStream(entityBytes));
             }
-            setEntityStream(new ByteArrayInputStream(entityBytes));
         }
     }
 
diff --git a/tests/e2e-inject/cdi-inject-weld/src/test/java/org/glassfish/jersey/tests/e2e/inject/cdi/weld/RequestContextBuilder.java b/tests/e2e-inject/cdi-inject-weld/src/test/java/org/glassfish/jersey/tests/e2e/inject/cdi/weld/RequestContextBuilder.java
index d4cc5c5..8f9c9c4 100644
--- a/tests/e2e-inject/cdi-inject-weld/src/test/java/org/glassfish/jersey/tests/e2e/inject/cdi/weld/RequestContextBuilder.java
+++ b/tests/e2e-inject/cdi-inject-weld/src/test/java/org/glassfish/jersey/tests/e2e/inject/cdi/weld/RequestContextBuilder.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2021 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2021, 2022 Oracle and/or its affiliates. All rights reserved.
  *
  * This program and the accompanying materials are made available under the
  * terms of the Eclipse Public License v. 2.0, which is available at
@@ -80,31 +80,33 @@
         public void setWorkers(final MessageBodyWorkers workers) {
             super.setWorkers(workers);
             final byte[] entityBytes;
-            if (entity != null) {
-                final MultivaluedMap<String, Object> myMap = new MultivaluedHashMap<String, Object>(getHeaders());
-                final ByteArrayOutputStream baos = new ByteArrayOutputStream();
-                OutputStream stream = null;
-                try {
-                    stream = workers.writeTo(entity, entity.getClass(), entityType.getType(),
-                            new Annotation[0], getMediaType(),
-                            myMap,
-                            propertiesDelegate, baos, Collections.<WriterInterceptor>emptyList());
-                } catch (final IOException | WebApplicationException ex) {
-                    Logger.getLogger(TestContainerRequest.class.getName()).log(Level.SEVERE, null, ex);
-                } finally {
-                    if (stream != null) {
-                        try {
-                            stream.close();
-                        } catch (final IOException e) {
-                            // ignore
+            if (workers != null) {
+                if (entity != null) {
+                    final MultivaluedMap<String, Object> myMap = new MultivaluedHashMap<String, Object>(getHeaders());
+                    final ByteArrayOutputStream baos = new ByteArrayOutputStream();
+                    OutputStream stream = null;
+                    try {
+                        stream = workers.writeTo(entity, entity.getClass(), entityType.getType(),
+                                new Annotation[0], getMediaType(),
+                                myMap,
+                                propertiesDelegate, baos, Collections.<WriterInterceptor>emptyList());
+                    } catch (final IOException | WebApplicationException ex) {
+                        Logger.getLogger(TestContainerRequest.class.getName()).log(Level.SEVERE, null, ex);
+                    } finally {
+                        if (stream != null) {
+                            try {
+                                stream.close();
+                            } catch (final IOException e) {
+                                // ignore
+                            }
                         }
                     }
+                    entityBytes = baos.toByteArray();
+                } else {
+                    entityBytes = new byte[0];
                 }
-                entityBytes = baos.toByteArray();
-            } else {
-                entityBytes = new byte[0];
+                setEntityStream(new ByteArrayInputStream(entityBytes));
             }
-            setEntityStream(new ByteArrayInputStream(entityBytes));
         }
     }
 
diff --git a/tests/e2e-inject/cdi2-se/src/test/java/org/glassfish/jersey/tests/e2e/inject/cdi/se/RequestContextBuilder.java b/tests/e2e-inject/cdi2-se/src/test/java/org/glassfish/jersey/tests/e2e/inject/cdi/se/RequestContextBuilder.java
index 1b0698d..65bdac5 100644
--- a/tests/e2e-inject/cdi2-se/src/test/java/org/glassfish/jersey/tests/e2e/inject/cdi/se/RequestContextBuilder.java
+++ b/tests/e2e-inject/cdi2-se/src/test/java/org/glassfish/jersey/tests/e2e/inject/cdi/se/RequestContextBuilder.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017, 2019 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2017, 2022 Oracle and/or its affiliates. All rights reserved.
  *
  * This program and the accompanying materials are made available under the
  * terms of the Eclipse Public License v. 2.0, which is available at
@@ -80,31 +80,33 @@
         public void setWorkers(final MessageBodyWorkers workers) {
             super.setWorkers(workers);
             final byte[] entityBytes;
-            if (entity != null) {
-                final MultivaluedMap<String, Object> myMap = new MultivaluedHashMap<String, Object>(getHeaders());
-                final ByteArrayOutputStream baos = new ByteArrayOutputStream();
-                OutputStream stream = null;
-                try {
-                    stream = workers.writeTo(entity, entity.getClass(), entityType.getType(),
-                            new Annotation[0], getMediaType(),
-                            myMap,
-                            propertiesDelegate, baos, Collections.<WriterInterceptor>emptyList());
-                } catch (final IOException | WebApplicationException ex) {
-                    Logger.getLogger(TestContainerRequest.class.getName()).log(Level.SEVERE, null, ex);
-                } finally {
-                    if (stream != null) {
-                        try {
-                            stream.close();
-                        } catch (final IOException e) {
-                            // ignore
+            if (workers != null) {
+                if (entity != null) {
+                    final MultivaluedMap<String, Object> myMap = new MultivaluedHashMap<String, Object>(getHeaders());
+                    final ByteArrayOutputStream baos = new ByteArrayOutputStream();
+                    OutputStream stream = null;
+                    try {
+                        stream = workers.writeTo(entity, entity.getClass(), entityType.getType(),
+                                new Annotation[0], getMediaType(),
+                                myMap,
+                                propertiesDelegate, baos, Collections.<WriterInterceptor>emptyList());
+                    } catch (final IOException | WebApplicationException ex) {
+                        Logger.getLogger(TestContainerRequest.class.getName()).log(Level.SEVERE, null, ex);
+                    } finally {
+                        if (stream != null) {
+                            try {
+                                stream.close();
+                            } catch (final IOException e) {
+                                // ignore
+                            }
                         }
                     }
+                    entityBytes = baos.toByteArray();
+                } else {
+                    entityBytes = new byte[0];
                 }
-                entityBytes = baos.toByteArray();
-            } else {
-                entityBytes = new byte[0];
+                setEntityStream(new ByteArrayInputStream(entityBytes));
             }
-            setEntityStream(new ByteArrayInputStream(entityBytes));
         }
     }