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

heneveld pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/brooklyn-server.git


The following commit(s) were added to refs/heads/master by this push:
     new 3b60d40f6b better handling of some errors
3b60d40f6b is described below

commit 3b60d40f6b43b0fc04717b8511bb08f682a51224
Author: Alex Heneveld <[email protected]>
AuthorDate: Thu Jul 27 12:08:14 2023 +0100

    better handling of some errors
---
 .../brooklyn/core/mgmt/rebind/RebindIteration.java |  5 +++-
 .../proxy/AbstractBrooklynObjectProxyImpl.java     |  3 ++-
 .../core/workflow/WorkflowErrorHandling.java       |  4 +++-
 .../core/json/ConfigurableSerializerProvider.java  | 13 +++++++++-
 .../workflow/WorkflowPersistReplayErrorsTest.java  |  2 +-
 .../brooklyn/rest/resources/SensorResource.java    | 28 ++++++++++++++--------
 6 files changed, 40 insertions(+), 15 deletions(-)

diff --git 
a/core/src/main/java/org/apache/brooklyn/core/mgmt/rebind/RebindIteration.java 
b/core/src/main/java/org/apache/brooklyn/core/mgmt/rebind/RebindIteration.java
index a7675af57d..a7c06cd2e4 100644
--- 
a/core/src/main/java/org/apache/brooklyn/core/mgmt/rebind/RebindIteration.java
+++ 
b/core/src/main/java/org/apache/brooklyn/core/mgmt/rebind/RebindIteration.java
@@ -31,6 +31,7 @@ import java.io.InputStream;
 import java.util.concurrent.Semaphore;
 import java.util.concurrent.atomic.AtomicBoolean;
 import java.util.concurrent.atomic.AtomicInteger;
+import java.util.stream.Collectors;
 
 import com.google.common.annotations.Beta;
 import org.apache.brooklyn.api.catalog.BrooklynCatalog;
@@ -591,6 +592,7 @@ public abstract class RebindIteration {
             adjunctProxies.entrySet().forEach(entry -> {
                 if (entry.getValue() instanceof Policy) 
exceptionHandler.onDanglingPolicyRef(entry.getKey());
                 else if (entry.getValue() instanceof Enricher) 
exceptionHandler.onDanglingEnricherRef(entry.getKey());
+                else if (entry.getValue() instanceof Feed) 
exceptionHandler.onDanglingFeedRef(entry.getKey());
                 else {
                     LOG.warn("Adjunct proxy for "+entry.getKey()+" is of 
unexpected type; "+entry.getValue()+"; reporting as dangling of unknown type");
                     exceptionHandler.onDanglingUntypedItemRef(entry.getKey());
@@ -1451,7 +1453,8 @@ public abstract class RebindIteration {
                 }
             }
             throw new IllegalStateException("Cannot instantiate instance of 
type " + clazz +
-                    "; expected constructor signature not found (" + args + 
")");
+                    "; expected constructor signature not found (" + args + " 
/ " +
+                    Arrays.asList(args).stream().map(a -> 
a.getClass()).collect(Collectors.toList()) + ")");
         }
 
         protected ManagedBundle newManagedBundle(ManagedBundleMemento 
bundleMemento) {
diff --git 
a/core/src/main/java/org/apache/brooklyn/core/objs/proxy/AbstractBrooklynObjectProxyImpl.java
 
b/core/src/main/java/org/apache/brooklyn/core/objs/proxy/AbstractBrooklynObjectProxyImpl.java
index 77af212352..d0779be29d 100644
--- 
a/core/src/main/java/org/apache/brooklyn/core/objs/proxy/AbstractBrooklynObjectProxyImpl.java
+++ 
b/core/src/main/java/org/apache/brooklyn/core/objs/proxy/AbstractBrooklynObjectProxyImpl.java
@@ -153,7 +153,8 @@ public abstract class AbstractBrooklynObjectProxyImpl<T 
extends BrooklynObject>
             if ("getId".equals(sig.name)) return getId();
             if ("hashCode".equals(sig.name)) return hashCode();
             if ("equals".equals(sig.name) && args.length==1) return 
equals(args[0]);
-            throw new NullPointerException("Access to proxy before 
initialized, method "+m);
+            throw new NullPointerException("Access to proxy on "+toString()+" 
before initialized, method "+m+"; " +
+                    "likely the target either is still being initialized or 
the target had an error when being created/rebinded");
         } else if (OBJECT_METHODS.contains(sig)) {
             result = m.invoke(delegate, args);
         } else if (isPermittedReadOnlyMethod(sig)) {
diff --git 
a/core/src/main/java/org/apache/brooklyn/core/workflow/WorkflowErrorHandling.java
 
b/core/src/main/java/org/apache/brooklyn/core/workflow/WorkflowErrorHandling.java
index 2961e2353e..e12bc0062f 100644
--- 
a/core/src/main/java/org/apache/brooklyn/core/workflow/WorkflowErrorHandling.java
+++ 
b/core/src/main/java/org/apache/brooklyn/core/workflow/WorkflowErrorHandling.java
@@ -256,7 +256,9 @@ public class WorkflowErrorHandling implements 
Callable<WorkflowErrorHandling.Wor
 
         // don't consider replaying automatically here; only done at workflow 
level
 
-        logWarnOnExceptionOrDebugIfKnown(entity, error, "Error in step '" + 
stepTaskThrowingError.getDisplayName() + "'; " + problemHere + "rethrowing: " + 
Exceptions.collapseText(error));
+        logWarnOnExceptionOrDebugIfKnown(entity, error,
+                currentStepInstance.getWorkflowExectionContext().getName() + 
": " +
+                "Error in step '" + stepTaskThrowingError.getDisplayName() + 
"'; " + problemHere + "rethrowing: " + Exceptions.collapseText(error));
         throw Exceptions.propagate(error);
     }
 
diff --git 
a/core/src/main/java/org/apache/brooklyn/util/core/json/ConfigurableSerializerProvider.java
 
b/core/src/main/java/org/apache/brooklyn/util/core/json/ConfigurableSerializerProvider.java
index 055f289e43..f2b45831c3 100644
--- 
a/core/src/main/java/org/apache/brooklyn/util/core/json/ConfigurableSerializerProvider.java
+++ 
b/core/src/main/java/org/apache/brooklyn/util/core/json/ConfigurableSerializerProvider.java
@@ -29,10 +29,14 @@ import com.fasterxml.jackson.databind.JsonSerializer;
 import com.fasterxml.jackson.databind.SerializationConfig;
 import com.fasterxml.jackson.databind.ser.DefaultSerializerProvider;
 import com.fasterxml.jackson.databind.ser.SerializerFactory;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 /** allows the serializer-of-last-resort to be customized, ie used for 
unknown-types */
 final class ConfigurableSerializerProvider extends DefaultSerializerProvider {
 
+    private static final Logger log = 
LoggerFactory.getLogger(ConfigurableSerializerProvider.class);
+
     private static final long serialVersionUID = 6094990395562170217L;
     protected JsonSerializer<Object> unknownTypeSerializer;
 
@@ -83,7 +87,14 @@ final class ConfigurableSerializerProvider extends 
DefaultSerializerProvider {
 
         JsonSerializer<Object> unknownTypeSerializer = 
getUnknownTypeSerializer(value.getClass());
         if (unknownTypeSerializer instanceof 
ErrorAndToStringUnknownTypeSerializer) {
-            
((ErrorAndToStringUnknownTypeSerializer)unknownTypeSerializer).serializeFromError(ctxt,
 e, value, jgen, this);
+            try {
+                ((ErrorAndToStringUnknownTypeSerializer) 
unknownTypeSerializer).serializeFromError(ctxt, e, value, jgen, this);
+            } catch (Exception e2) {
+                Exceptions.propagateIfFatal(e2);
+                log.warn("Unable to nicely recover from original error during 
serialization "+e+"; got "+e2+"; rethrowing original");
+                log.trace("Secondary error", e2);
+                throw Exceptions.propagate(e);
+            }
         } else {
             unknownTypeSerializer.serialize(value, jgen, this);
         }
diff --git 
a/core/src/test/java/org/apache/brooklyn/core/workflow/WorkflowPersistReplayErrorsTest.java
 
b/core/src/test/java/org/apache/brooklyn/core/workflow/WorkflowPersistReplayErrorsTest.java
index 7f3843b79c..e85f5af11c 100644
--- 
a/core/src/test/java/org/apache/brooklyn/core/workflow/WorkflowPersistReplayErrorsTest.java
+++ 
b/core/src/test/java/org/apache/brooklyn/core/workflow/WorkflowPersistReplayErrorsTest.java
@@ -632,7 +632,7 @@ public class WorkflowPersistReplayErrorsTest extends 
RebindTestFixture<BasicAppl
             Asserts.assertEntriesSatisfy(msgs, MutableList.of(
                     m -> m.matches("Starting workflow 'myWorkflow .workflow 
effector.', moving to first step .*-1"),
                     m -> m.matches("Starting step .*-1 in task .*"),
-                    m -> m.matches("Error in step '1 - invoke-effector 
does-not-exist'; rethrowing: No effector matching 'does-not-exist'"),
+                    m -> m.matches("myWorkflow .*: Error in step '1 - 
invoke-effector does-not-exist'; rethrowing: No effector matching 
'does-not-exist'"),
                     m -> m.matches("Error in workflow 'myWorkflow .workflow 
effector.' around step .*-1, running error handler"),
                     m -> m.matches("Encountered error in workflow .*/.* 
'myWorkflow' .handler present.: No effector matching 'does-not-exist'"),
                     m -> m.matches("Starting .*-error-handler with 1 step in 
task .*"),
diff --git 
a/rest/rest-resources/src/main/java/org/apache/brooklyn/rest/resources/SensorResource.java
 
b/rest/rest-resources/src/main/java/org/apache/brooklyn/rest/resources/SensorResource.java
index cecde9a850..e79d037301 100644
--- 
a/rest/rest-resources/src/main/java/org/apache/brooklyn/rest/resources/SensorResource.java
+++ 
b/rest/rest-resources/src/main/java/org/apache/brooklyn/rest/resources/SensorResource.java
@@ -36,6 +36,8 @@ import org.apache.brooklyn.rest.filter.HaHotStateRequired;
 import org.apache.brooklyn.rest.transform.SensorTransformer;
 import org.apache.brooklyn.rest.util.EntityAttributesUtils;
 import org.apache.brooklyn.rest.util.WebResourceUtils;
+import org.apache.brooklyn.util.collections.MutableMap;
+import org.apache.brooklyn.util.exceptions.Exceptions;
 import org.apache.brooklyn.util.text.Strings;
 import org.apache.brooklyn.util.time.Duration;
 import org.slf4j.Logger;
@@ -85,17 +87,23 @@ public class SensorResource extends 
AbstractBrooklynRestResource implements Sens
         Iterable<AttributeSensor> sensors = 
filter(entity.getEntityType().getSensors(), AttributeSensor.class);
 
         for (AttributeSensor<?> sensor : sensors) {
-            // Exclude sensors that user is not allowed to see
-            if (!Entitlements.isEntitled(mgmt().getEntitlementManager(), 
Entitlements.SEE_SENSOR, new EntityAndItem<String>(entity, sensor.getName()))) {
-                log.trace("User {} not authorized to see sensor {} of entity 
{}; excluding from current-state results", 
-                        new Object[] 
{Entitlements.getEntitlementContext().user(), sensor.getName(), entity});
-                continue;
+            try {
+                // Exclude sensors that user is not allowed to see
+                if (!Entitlements.isEntitled(mgmt().getEntitlementManager(), 
Entitlements.SEE_SENSOR, new EntityAndItem<String>(entity, sensor.getName()))) {
+                    log.trace("User {} not authorized to see sensor {} of 
entity {}; excluding from current-state results",
+                            new 
Object[]{Entitlements.getEntitlementContext().user(), sensor.getName(), 
entity});
+                    continue;
+                }
+
+                Object value = EntityAttributesUtils.tryGetAttribute(entity, 
findSensor(entity, sensor.getName()));
+                sensorMap.put(sensor.getName(),
+                        
resolving(value).preferJson(true).asJerseyOutermostReturnValue(false).useDisplayHints(useDisplayHints).raw(raw).context(entity).timeout(Duration.ZERO).renderAs(sensor)
+                                .suppressIfSecret(sensor.getName(), 
suppressSecrets).filterOutputFields(sensor.getName().startsWith("internal")).resolve());
+            } catch (Exception e) {
+                Exceptions.propagateIfFatal(e);
+                log.error(""+sensor+" on "+entity+" cannot be serialized for 
REST output; ignoring: "+e, e);
+                sensorMap.put(sensor.getName(), MutableMap.of("type", "error", 
"message", "Value not available. See logs."));
             }
-
-            Object value = EntityAttributesUtils.tryGetAttribute(entity, 
findSensor(entity, sensor.getName()));
-            sensorMap.put(sensor.getName(),
-                
resolving(value).preferJson(true).asJerseyOutermostReturnValue(false).useDisplayHints(useDisplayHints).raw(raw).context(entity).timeout(Duration.ZERO).renderAs(sensor)
-                        .suppressIfSecret(sensor.getName(), 
suppressSecrets).filterOutputFields(sensor.getName().startsWith("internal")).resolve());
         }
         return sensorMap;
     }

Reply via email to