From 11bcd2d1db02ff2dbb2a8e560e3f09fe37057796 Mon Sep 17 00:00:00 2001 From: gss2002 Date: Tue, 11 Oct 2016 00:09:23 -0400 Subject: [PATCH 1/2] ZEPPELIN-1516 Static/Singleton for userSessionMaps --- .../org/apache/zeppelin/livy/LivyHelper.java | 45 ++++++++++---- .../zeppelin/livy/LivyPySparkInterpreter.java | 16 ++--- .../zeppelin/livy/LivyPySparkSessionMap.java | 59 +++++++++++++++++++ .../zeppelin/livy/LivySparkInterpreter.java | 23 +++----- .../zeppelin/livy/LivySparkRInterpreter.java | 15 ++--- .../zeppelin/livy/LivySparkRSessionMap.java | 59 +++++++++++++++++++ .../livy/LivySparkSQLInterpreter.java | 15 ++--- .../zeppelin/livy/LivySparkSessionMap.java | 59 +++++++++++++++++++ 8 files changed, 243 insertions(+), 48 deletions(-) create mode 100644 livy/src/main/java/org/apache/zeppelin/livy/LivyPySparkSessionMap.java create mode 100644 livy/src/main/java/org/apache/zeppelin/livy/LivySparkRSessionMap.java create mode 100644 livy/src/main/java/org/apache/zeppelin/livy/LivySparkSessionMap.java diff --git a/livy/src/main/java/org/apache/zeppelin/livy/LivyHelper.java b/livy/src/main/java/org/apache/zeppelin/livy/LivyHelper.java index 0b09e282e2e..ce0e541cdef 100644 --- a/livy/src/main/java/org/apache/zeppelin/livy/LivyHelper.java +++ b/livy/src/main/java/org/apache/zeppelin/livy/LivyHelper.java @@ -49,9 +49,14 @@ public class LivyHelper { Gson gson = new GsonBuilder().setPrettyPrinting().create(); HashMap paragraphHttpMap = new HashMap<>(); Properties property; + String type; + String SPARK = "spark"; + String SPARKR = "sparkr"; + String PYSPARK = "pyspark"; - LivyHelper(Properties property) { + LivyHelper(Properties property, String type) { this.property = property; + this.type = type; } public Integer createSession(InterpreterContext context, String kind) throws Exception { @@ -132,7 +137,6 @@ public Integer createSession(InterpreterContext context, String kind) throws Exc public InterpreterResult interpretInput(String stringLines, final InterpreterContext context, - final Map userSessionMap, LivyOutputStream out) { try { String[] lines = stringLines.split("\n"); @@ -182,7 +186,7 @@ public InterpreterResult interpretInput(String stringLines, InterpreterResult res; try { - res = interpret(incomplete + s, context, userSessionMap); + res = interpret(incomplete + s, context); } catch (Exception e) { LOGGER.error("Interpreter exception", e); return new InterpreterResult(Code.ERROR, InterpreterUtils.getMostRelevantMessage(e)); @@ -216,8 +220,7 @@ public InterpreterResult interpretInput(String stringLines, } public InterpreterResult interpret(String stringLines, - final InterpreterContext context, - final Map userSessionMap) + final InterpreterContext context) throws Exception { stringLines = stringLines //for "\n" present in string @@ -232,7 +235,7 @@ public InterpreterResult interpret(String stringLines, if (stringLines.trim().equals("")) { return new InterpreterResult(Code.SUCCESS, ""); } - Map jsonMap = executeCommand(stringLines, context, userSessionMap); + Map jsonMap = executeCommand(stringLines, context); Integer id = ((Double) jsonMap.get("id")).intValue(); InterpreterResult res = getResultFromMap(jsonMap); if (res != null) { @@ -244,7 +247,7 @@ public InterpreterResult interpret(String stringLines, if (paragraphHttpMap.get(context.getParagraphId()) == null) { return new InterpreterResult(Code.INCOMPLETE, ""); } - jsonMap = getStatusById(context, userSessionMap, id); + jsonMap = getStatusById(context, id); InterpreterResult interpreterResult = getResultFromMap(jsonMap); if (interpreterResult != null) { return interpreterResult; @@ -289,10 +292,10 @@ private InterpreterResult getResultFromMap(Map jsonMap) { return null; } - private Map executeCommand(String lines, InterpreterContext context, - Map userSessionMap) throws Exception { + private Map executeCommand(String lines, InterpreterContext context + ) throws Exception { String json = executeHTTP(property.get("zeppelin.livy.url") + "/sessions/" - + userSessionMap.get(context.getAuthenticationInfo().getUser()) + + getUserSessionId(context) + "/statements", "POST", "{\"code\": \"" + lines + "\" }", @@ -311,11 +314,29 @@ private Map executeCommand(String lines, InterpreterContext context, throw e; } } + + private Integer getUserSessionId(InterpreterContext context) { + Integer sessionId = null; + if (this.type.equalsIgnoreCase(SPARK)){ + sessionId = LivySparkSessionMap.getInstance().getSparkUserSession(context + .getAuthenticationInfo().getUser()); + } + if (this.type.equalsIgnoreCase(SPARKR)){ + sessionId = LivySparkRSessionMap.getInstance().getSparkUserSession(context + .getAuthenticationInfo().getUser()); + } + if (this.type.equalsIgnoreCase(PYSPARK)){ + sessionId = LivyPySparkSessionMap.getInstance().getSparkUserSession(context + .getAuthenticationInfo().getUser()); + } + return sessionId; + } private Map getStatusById(InterpreterContext context, - Map userSessionMap, Integer id) throws Exception { + Integer id) throws Exception { + String json = executeHTTP(property.getProperty("zeppelin.livy.url") + "/sessions/" - + userSessionMap.get(context.getAuthenticationInfo().getUser()) + + getUserSessionId(context) + "/statements/" + id, "GET", null, context.getParagraphId()); try { diff --git a/livy/src/main/java/org/apache/zeppelin/livy/LivyPySparkInterpreter.java b/livy/src/main/java/org/apache/zeppelin/livy/LivyPySparkInterpreter.java index bd342a2e3ed..7791986b172 100644 --- a/livy/src/main/java/org/apache/zeppelin/livy/LivyPySparkInterpreter.java +++ b/livy/src/main/java/org/apache/zeppelin/livy/LivyPySparkInterpreter.java @@ -37,13 +37,15 @@ public class LivyPySparkInterpreter extends Interpreter { Logger LOGGER = LoggerFactory.getLogger(LivyPySparkInterpreter.class); - protected Map userSessionMap; + private LivyPySparkSessionMap lsmap; protected LivyHelper livyHelper; + private String type = "pyspark"; + public LivyPySparkInterpreter(Properties property) { super(property); - userSessionMap = new HashMap<>(); - livyHelper = new LivyHelper(property); + lsmap = LivyPySparkSessionMap.getInstance(); + livyHelper = new LivyHelper(property, type); } @Override @@ -52,15 +54,15 @@ public void open() { @Override public void close() { - livyHelper.closeSession(userSessionMap); + livyHelper.closeSession(lsmap.getSparkUserSessionMap()); } @Override public InterpreterResult interpret(String line, InterpreterContext interpreterContext) { try { - if (userSessionMap.get(interpreterContext.getAuthenticationInfo().getUser()) == null) { + if (lsmap.getSparkUserSession(interpreterContext.getAuthenticationInfo().getUser()) == null) { try { - userSessionMap.put( + lsmap.setSparkUserSessionMap( interpreterContext.getAuthenticationInfo().getUser(), livyHelper.createSession( interpreterContext, @@ -76,7 +78,7 @@ public InterpreterResult interpret(String line, InterpreterContext interpreterCo return new InterpreterResult(InterpreterResult.Code.SUCCESS, ""); } - return livyHelper.interpret(line, interpreterContext, userSessionMap); + return livyHelper.interpret(line, interpreterContext); } catch (Exception e) { LOGGER.error("Exception in LivyPySparkInterpreter while interpret ", e); return new InterpreterResult(InterpreterResult.Code.ERROR, diff --git a/livy/src/main/java/org/apache/zeppelin/livy/LivyPySparkSessionMap.java b/livy/src/main/java/org/apache/zeppelin/livy/LivyPySparkSessionMap.java new file mode 100644 index 00000000000..90bd91ac4e1 --- /dev/null +++ b/livy/src/main/java/org/apache/zeppelin/livy/LivyPySparkSessionMap.java @@ -0,0 +1,59 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.zeppelin.livy; + +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +/** + * Livy PySparkSessionMap for Zeppelin. + */ +public class LivyPySparkSessionMap { + private static LivyPySparkSessionMap instance = null; + protected static Map userSparkSessionMap = + new ConcurrentHashMap(); + private static Object mutex = new Object(); + + + protected LivyPySparkSessionMap() { + // Exists only to defeat instantiation + } + public static LivyPySparkSessionMap getInstance() { + if (instance == null) { + synchronized (mutex){ + if (instance == null) instance = new LivyPySparkSessionMap(); + } + } + return instance; + } + public void setSparkUserSessionMap(String user, Integer sessionInt) { + userSparkSessionMap.put(user, sessionInt); + } + public void deleteSparkUserSessionMap(String user, Integer sessionInt) { + userSparkSessionMap.remove(user, sessionInt); + } + public void deleteSparkUserSessionMap(String user) { + userSparkSessionMap.remove(user); + } + public Integer getSparkUserSession(String user) { + return userSparkSessionMap.get(user); + } + public Map getSparkUserSessionMap() { + return userSparkSessionMap; + } +} diff --git a/livy/src/main/java/org/apache/zeppelin/livy/LivySparkInterpreter.java b/livy/src/main/java/org/apache/zeppelin/livy/LivySparkInterpreter.java index 95ee22e89e8..3d540d3aabb 100644 --- a/livy/src/main/java/org/apache/zeppelin/livy/LivySparkInterpreter.java +++ b/livy/src/main/java/org/apache/zeppelin/livy/LivySparkInterpreter.java @@ -37,39 +37,32 @@ public class LivySparkInterpreter extends Interpreter { Logger LOGGER = LoggerFactory.getLogger(LivySparkInterpreter.class); private LivyOutputStream out; - protected static Map userSessionMap; private LivyHelper livyHelper; + private LivySparkSessionMap lsmap; + private String type = "spark"; public LivySparkInterpreter(Properties property) { super(property); - userSessionMap = new HashMap<>(); - livyHelper = new LivyHelper(property); + lsmap = LivySparkSessionMap.getInstance(); + livyHelper = new LivyHelper(property, type); out = new LivyOutputStream(); } - protected static Map getUserSessionMap() { - return userSessionMap; - } - - public void setUserSessionMap(Map userSessionMap) { - this.userSessionMap = userSessionMap; - } - @Override public void open() { } @Override public void close() { - livyHelper.closeSession(userSessionMap); + livyHelper.closeSession(lsmap.getSparkUserSessionMap()); } @Override public InterpreterResult interpret(String line, InterpreterContext interpreterContext) { try { - if (userSessionMap.get(interpreterContext.getAuthenticationInfo().getUser()) == null) { + if (lsmap.getSparkUserSession(interpreterContext.getAuthenticationInfo().getUser()) == null) { try { - userSessionMap.put( + lsmap.setSparkUserSessionMap( interpreterContext.getAuthenticationInfo().getUser(), livyHelper.createSession( interpreterContext, @@ -84,7 +77,7 @@ public InterpreterResult interpret(String line, InterpreterContext interpreterCo return new InterpreterResult(InterpreterResult.Code.SUCCESS, ""); } - return livyHelper.interpretInput(line, interpreterContext, userSessionMap, out); + return livyHelper.interpretInput(line, interpreterContext, out); } catch (Exception e) { LOGGER.error("Exception in LivySparkInterpreter while interpret ", e); return new InterpreterResult(InterpreterResult.Code.ERROR, diff --git a/livy/src/main/java/org/apache/zeppelin/livy/LivySparkRInterpreter.java b/livy/src/main/java/org/apache/zeppelin/livy/LivySparkRInterpreter.java index 753b378e9a1..9e05b0e6b25 100644 --- a/livy/src/main/java/org/apache/zeppelin/livy/LivySparkRInterpreter.java +++ b/livy/src/main/java/org/apache/zeppelin/livy/LivySparkRInterpreter.java @@ -37,13 +37,14 @@ public class LivySparkRInterpreter extends Interpreter { Logger LOGGER = LoggerFactory.getLogger(LivySparkRInterpreter.class); - protected Map userSessionMap; private LivyHelper livyHelper; + private LivySparkRSessionMap lsmap; + private String type = "sparkr"; public LivySparkRInterpreter(Properties property) { super(property); - userSessionMap = new HashMap<>(); - livyHelper = new LivyHelper(property); + lsmap = LivySparkRSessionMap.getInstance(); + livyHelper = new LivyHelper(property, type); } @Override @@ -52,15 +53,15 @@ public void open() { @Override public void close() { - livyHelper.closeSession(userSessionMap); + livyHelper.closeSession(lsmap.getSparkUserSessionMap()); } @Override public InterpreterResult interpret(String line, InterpreterContext interpreterContext) { try { - if (userSessionMap.get(interpreterContext.getAuthenticationInfo().getUser()) == null) { + if (lsmap.getSparkUserSession(interpreterContext.getAuthenticationInfo().getUser()) == null) { try { - userSessionMap.put( + lsmap.setSparkUserSessionMap( interpreterContext.getAuthenticationInfo().getUser(), livyHelper.createSession( interpreterContext, @@ -76,7 +77,7 @@ public InterpreterResult interpret(String line, InterpreterContext interpreterCo return new InterpreterResult(InterpreterResult.Code.SUCCESS, ""); } - return livyHelper.interpret(line, interpreterContext, userSessionMap); + return livyHelper.interpret(line, interpreterContext); } catch (Exception e) { LOGGER.error("Exception in LivySparkRInterpreter while interpret ", e); return new InterpreterResult(InterpreterResult.Code.ERROR, diff --git a/livy/src/main/java/org/apache/zeppelin/livy/LivySparkRSessionMap.java b/livy/src/main/java/org/apache/zeppelin/livy/LivySparkRSessionMap.java new file mode 100644 index 00000000000..8f36b913481 --- /dev/null +++ b/livy/src/main/java/org/apache/zeppelin/livy/LivySparkRSessionMap.java @@ -0,0 +1,59 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.zeppelin.livy; + +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +/** + * Livy SparkRSessionMap for Zeppelin. + */ +public class LivySparkRSessionMap { + private static LivySparkRSessionMap instance = null; + protected static Map userSparkSessionMap = + new ConcurrentHashMap(); + private static Object mutex = new Object(); + + + protected LivySparkRSessionMap() { + // Exists only to defeat instantiation + } + public static LivySparkRSessionMap getInstance() { + if (instance == null) { + synchronized (mutex){ + if (instance == null) instance = new LivySparkRSessionMap(); + } + } + return instance; + } + public void setSparkUserSessionMap(String user, Integer sessionInt) { + userSparkSessionMap.put(user, sessionInt); + } + public void deleteSparkUserSessionMap(String user, Integer sessionInt) { + userSparkSessionMap.remove(user, sessionInt); + } + public void deleteSparkUserSessionMap(String user) { + userSparkSessionMap.remove(user); + } + public Integer getSparkUserSession(String user) { + return userSparkSessionMap.get(user); + } + public Map getSparkUserSessionMap() { + return userSparkSessionMap; + } +} diff --git a/livy/src/main/java/org/apache/zeppelin/livy/LivySparkSQLInterpreter.java b/livy/src/main/java/org/apache/zeppelin/livy/LivySparkSQLInterpreter.java index 3d4a0f4e428..d75505002c9 100644 --- a/livy/src/main/java/org/apache/zeppelin/livy/LivySparkSQLInterpreter.java +++ b/livy/src/main/java/org/apache/zeppelin/livy/LivySparkSQLInterpreter.java @@ -36,13 +36,14 @@ public class LivySparkSQLInterpreter extends Interpreter { Logger LOGGER = LoggerFactory.getLogger(LivySparkSQLInterpreter.class); - protected Map userSessionMap; private LivyHelper livyHelper; + private LivySparkSessionMap lsmap; + private String type = "spark"; public LivySparkSQLInterpreter(Properties property) { super(property); - livyHelper = new LivyHelper(property); - userSessionMap = LivySparkInterpreter.getUserSessionMap(); + lsmap = LivySparkSessionMap.getInstance(); + livyHelper = new LivyHelper(property, type); } @Override @@ -51,15 +52,15 @@ public void open() { @Override public void close() { - livyHelper.closeSession(userSessionMap); + livyHelper.closeSession(lsmap.getSparkUserSessionMap()); } @Override public InterpreterResult interpret(String line, InterpreterContext interpreterContext) { try { - if (userSessionMap.get(interpreterContext.getAuthenticationInfo().getUser()) == null) { + if (lsmap.getSparkUserSession(interpreterContext.getAuthenticationInfo().getUser()) == null) { try { - userSessionMap.put( + lsmap.setSparkUserSessionMap( interpreterContext.getAuthenticationInfo().getUser(), livyHelper.createSession( interpreterContext, @@ -80,7 +81,7 @@ public InterpreterResult interpret(String line, InterpreterContext interpreterCo .replaceAll("\\n", " ") + "\").show(" + property.get("zeppelin.livy.spark.sql.maxResult") + ")", - interpreterContext, userSessionMap); + interpreterContext); if (res.code() == InterpreterResult.Code.SUCCESS) { StringBuilder resMsg = new StringBuilder(); diff --git a/livy/src/main/java/org/apache/zeppelin/livy/LivySparkSessionMap.java b/livy/src/main/java/org/apache/zeppelin/livy/LivySparkSessionMap.java new file mode 100644 index 00000000000..6a992dd9a23 --- /dev/null +++ b/livy/src/main/java/org/apache/zeppelin/livy/LivySparkSessionMap.java @@ -0,0 +1,59 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.zeppelin.livy; + +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +/** + * Livy SparkSessionMap for Zeppelin. + */ +public class LivySparkSessionMap { + private static LivySparkSessionMap instance = null; + protected static Map userSparkSessionMap = + new ConcurrentHashMap(); + private static Object mutex = new Object(); + + + protected LivySparkSessionMap() { + // Exists only to defeat instantiation + } + public static LivySparkSessionMap getInstance() { + if (instance == null) { + synchronized (mutex){ + if (instance == null) instance = new LivySparkSessionMap(); + } + } + return instance; + } + public void setSparkUserSessionMap(String user, Integer sessionInt) { + userSparkSessionMap.put(user, sessionInt); + } + public void deleteSparkUserSessionMap(String user, Integer sessionInt) { + userSparkSessionMap.remove(user, sessionInt); + } + public void deleteSparkUserSessionMap(String user) { + userSparkSessionMap.remove(user); + } + public Integer getSparkUserSession(String user) { + return userSparkSessionMap.get(user); + } + public Map getSparkUserSessionMap() { + return userSparkSessionMap; + } +} From 93c2b1488f6f3610c28a10537b18e3d394c8f9e2 Mon Sep 17 00:00:00 2001 From: gss2002 Date: Thu, 13 Oct 2016 12:28:42 -0400 Subject: [PATCH 2/2] ZEPPELIN-1546 Zeppelin Livy Interpreter Session Management Recovery --- .../org/apache/zeppelin/livy/LivyHelper.java | 53 ++++++++++++++++--- 1 file changed, 47 insertions(+), 6 deletions(-) diff --git a/livy/src/main/java/org/apache/zeppelin/livy/LivyHelper.java b/livy/src/main/java/org/apache/zeppelin/livy/LivyHelper.java index ce0e541cdef..4332887a1d9 100644 --- a/livy/src/main/java/org/apache/zeppelin/livy/LivyHelper.java +++ b/livy/src/main/java/org/apache/zeppelin/livy/LivyHelper.java @@ -28,12 +28,16 @@ import org.apache.zeppelin.interpreter.InterpreterUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.springframework.core.NestedRuntimeException; import org.springframework.http.HttpEntity; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpMethod; +import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.security.kerberos.client.KerberosRestTemplate; import org.springframework.web.client.HttpClientErrorException; +import org.springframework.web.client.RestClientException; +import org.springframework.web.client.RestClientResponseException; import org.springframework.web.client.RestTemplate; import java.nio.charset.Charset; @@ -294,15 +298,24 @@ private InterpreterResult getResultFromMap(Map jsonMap) { private Map executeCommand(String lines, InterpreterContext context ) throws Exception { + boolean clearSession = false; String json = executeHTTP(property.get("zeppelin.livy.url") + "/sessions/" + getUserSessionId(context) + "/statements", "POST", "{\"code\": \"" + lines + "\" }", context.getParagraphId()); - if (json.matches("^(\")?Session (\'[0-9]\' )?not found(.?\"?)$")) { + if (json != null) { + if (json.matches("^(\")?Session (\'[0-9]\' )?not found(.?\"?)$")) { + clearSession = true; + } + } else { + clearSession = true; + } + if (clearSession) { + removeSessionId(context); throw new Exception("Exception: Session not found, Livy server would have restarted, " + - "or lost session."); + "or lost session."); } try { Map jsonMap = gson.fromJson(json, @@ -331,6 +344,29 @@ private Integer getUserSessionId(InterpreterContext context) { } return sessionId; } + + private void removeSessionId(InterpreterContext context) { + Integer sessionId = null; + if (this.type.equalsIgnoreCase(SPARK)){ + sessionId = LivySparkSessionMap.getInstance().getSparkUserSession(context + .getAuthenticationInfo().getUser()); + LivySparkSessionMap.getInstance().deleteSparkUserSessionMap(context + .getAuthenticationInfo().getUser()); + } + if (this.type.equalsIgnoreCase(SPARKR)){ + sessionId = LivySparkRSessionMap.getInstance().getSparkUserSession(context + .getAuthenticationInfo().getUser()); + LivySparkRSessionMap.getInstance().deleteSparkUserSessionMap(context + .getAuthenticationInfo().getUser()); + } + if (this.type.equalsIgnoreCase(PYSPARK)){ + sessionId = LivyPySparkSessionMap.getInstance().getSparkUserSession(context + .getAuthenticationInfo().getUser()); + LivyPySparkSessionMap.getInstance().deleteSparkUserSessionMap(context + .getAuthenticationInfo().getUser()); + } + LOGGER.info(String.format("Removing Session from userSessionMap: %s", sessionId)); + } private Map getStatusById(InterpreterContext context, Integer id) throws Exception { @@ -380,10 +416,15 @@ protected String executeHTTP(String targetURL, String method, String jsonData, S HttpEntity entity = new HttpEntity(headers); response = restTemplate.exchange(targetURL, HttpMethod.DELETE, entity, String.class); } - } catch (HttpClientErrorException e) { - response = new ResponseEntity(e.getResponseBodyAsString(), e.getStatusCode()); - LOGGER.error(String.format("Error with %s StatusCode: %s", - response.getStatusCode().value(), e.getResponseBodyAsString())); + } catch (NestedRuntimeException e) { + // This needs to be a nestedException if not it cannot handle it due to HttpClientException being nested + if (e.getRootCause() instanceof HttpClientErrorException) { + HttpClientErrorException hce = (HttpClientErrorException) e.getRootCause(); + response = new ResponseEntity(hce.getResponseBodyAsString(), + HttpStatus.valueOf(hce.getRawStatusCode())); + LOGGER.error(String.format("Error with %s StatusCode: %s", + response.getStatusCode().value(), hce.getResponseBodyAsString())); + } } if (response == null) { return null;