From 7c2043b5a69eb65208a32ee52169a02e88a98171 Mon Sep 17 00:00:00 2001 From: OlivierDelcroix Date: Fri, 17 Apr 2020 14:13:46 +0200 Subject: [PATCH 01/11] improve trace logs --- .../remotese/rm/AbstractRemoteMethodTx.java | 48 ++++++++++++++----- 1 file changed, 36 insertions(+), 12 deletions(-) diff --git a/java/component/keyple-plugin/remotese/src/main/java/org/eclipse/keyple/plugin/remotese/rm/AbstractRemoteMethodTx.java b/java/component/keyple-plugin/remotese/src/main/java/org/eclipse/keyple/plugin/remotese/rm/AbstractRemoteMethodTx.java index 75cc20c16..f02cc00ef 100644 --- a/java/component/keyple-plugin/remotese/src/main/java/org/eclipse/keyple/plugin/remotese/rm/AbstractRemoteMethodTx.java +++ b/java/component/keyple-plugin/remotese/src/main/java/org/eclipse/keyple/plugin/remotese/rm/AbstractRemoteMethodTx.java @@ -95,6 +95,9 @@ void setTimeout(long timeout) { * @throws KeypleRemoteException if a problem occurs while sending */ public void send(IRemoteMethodTxCallback callback) throws KeypleRemoteException { + if(logger.isTraceEnabled()){ + logger.trace("Send asynchronously keypleDto for {}", this); + } this.callback = callback; sender.sendDTO(this.dto()); } @@ -110,12 +113,15 @@ public void send(IRemoteMethodTxCallback callback) throws KeypleRemoteExcepti */ final public T execute(IRemoteMethodTxEngine rmTxEngine) throws KeypleRemoteException { + if(logger.isTraceEnabled()){ + logger.trace("execute {}", this.toString()); + } // register this method to receive response rmTxEngine.register(this); if (!isRegistered) { throw new IllegalStateException( - "RemoteMethodTx#execute() can not be used until RemoteMethod is isRegistered in a RemoteMethodEngine, please call RemoteMethodEngine#register"); + "RemoteMethodTx#execute() can not be used until RemoteMethodTx is registered in a RemoteMethodEngine, please call RemoteMethodEngine#register"); } // logger.debug("Blocking Get {}", this.getClass().getCanonicalName()); final AbstractRemoteMethodTx thisInstance = this; @@ -127,13 +133,14 @@ public void run() { send(new IRemoteMethodTxCallback() { @Override public void get(T response, KeypleRemoteException exception) { - logger.debug("Release lock of rm {} {}", thisInstance.getMethodName(), - thisInstance.id); + if(logger.isTraceEnabled()){ + logger.trace("Release lock of {}", thisInstance.toString()); + } lock.countDown(); } }); } catch (KeypleRemoteException e) { - logger.error("Exception while sending Dto", e); + logger.error("Exception {} while sending Dto {} for {}", e.getMessage(), thisInstance); thisInstance.remoteException = e; lock.countDown(); } @@ -142,14 +149,18 @@ public void get(T response, KeypleRemoteException exception) { try { lock = new CountDownLatch(1); - logger.trace("" + "" + "Set callback on RemoteMethodTx {} {}", - this.getClass().getCanonicalName(), this.hashCode()); asyncSend.start(); - logger.trace("Lock {}, {}", thisInstance.getMethodName(), this.id); + if(logger.isTraceEnabled()){ + logger.trace("Lock thread for {}",this.toString()); + } + + // lock until response is received boolean responseReceived = lock.await(timeout, TimeUnit.MILLISECONDS); if (responseReceived) { - logger.trace("Unlock {}, {}", this.getClass().getCanonicalName(), this.hashCode()); + if(logger.isTraceEnabled()){ + logger.trace("Unlock thread for {}",this.toString()); + } if (this.remoteException != null) { throw remoteException; } else { @@ -160,14 +171,13 @@ public void get(T response, KeypleRemoteException exception) { * timeout, no answer has been received */ throw new KeypleRemoteException( - "Waiting time elapsed, no answer received from the other node for method " - + this.getClass().getCanonicalName()); + "Waiting time elapsed, no answer received from the other node for " + this.toString()); } } catch (InterruptedException e) { throw new IllegalStateException( - "Thread locking in blocking transmitSet has encountered an exception", e); + "Thread locking has encounterd an exception with "+ this.toString(), e); } } @@ -177,6 +187,9 @@ public void get(T response, KeypleRemoteException exception) { * @param keypleDto */ void setResponse(KeypleDto keypleDto) { + if(logger.isTraceEnabled()){ + logger.trace("Response received {} for {}",keypleDto, this.toString()); + } try { this.response = parseResponse(keypleDto); this.callback.get(response, null); @@ -203,5 +216,16 @@ public void setRegistered(Boolean registered) { protected abstract KeypleDto dto(); - + @Override + public String toString() { + return "AbstractRemoteMethodTx{" + + "sessionId='" + sessionId + '\'' + + ", methodName='" + getMethodName() + '\'' + + ", nativeReaderName='" + nativeReaderName + '\'' + + ", virtualReaderName='" + virtualReaderName + '\'' + + ", targetNodeId='" + targetNodeId + '\'' + + ", requesterNodeId='" + requesterNodeId + '\'' + + ", id='" + id + '\'' + + '}'; + } } From 8954eb93689519e41d82abe31cda2362f3943c7b Mon Sep 17 00:00:00 2001 From: OlivierDelcroix Date: Fri, 17 Apr 2020 14:31:59 +0200 Subject: [PATCH 02/11] fix NPE --- .../remotese/rm/RemoteMethodTxEngine.java | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/java/component/keyple-plugin/remotese/src/main/java/org/eclipse/keyple/plugin/remotese/rm/RemoteMethodTxEngine.java b/java/component/keyple-plugin/remotese/src/main/java/org/eclipse/keyple/plugin/remotese/rm/RemoteMethodTxEngine.java index ad4f427c9..e9375375c 100644 --- a/java/component/keyple-plugin/remotese/src/main/java/org/eclipse/keyple/plugin/remotese/rm/RemoteMethodTxEngine.java +++ b/java/component/keyple-plugin/remotese/src/main/java/org/eclipse/keyple/plugin/remotese/rm/RemoteMethodTxEngine.java @@ -76,19 +76,28 @@ public TransportDto onDTO(TransportDto message) { */ if (remoteMethodTx == null) { /* - * Should not happen, response received does not match a request. Ignore it + * Response received does not match a request. Ignore it */ logger.error( "RemoteMethodTxEngine receives a KeypleDto response but no remoteMethodTx are defined : " + keypleDto); + + } else { + + /* + * Set keypleDto as a response to the remote method Tx (request) + */ + remoteMethodTx.setResponse(keypleDto); } - // only one operation is allowed at the time - remoteMethodTx.setResponse(keypleDto); + /* + * init remote engine to receive a new request + */ // re init remoteMethod remoteMethodTx = null; + // no dto should be sent back return message.nextTransportDTO(KeypleDtoHelper.NoResponse(keypleDto.getId())); } @@ -99,7 +108,9 @@ public TransportDto onDTO(TransportDto message) { */ @Override public void register(final AbstractRemoteMethodTx rm) { - logger.debug("Register rm to engine : {} {}", rm.getMethodName(), rm.id); + if (logger.isTraceEnabled()) { + logger.trace("Register RemoteMethod to engine : {} ", rm.id); + } rm.setRegistered(true); remoteMethodTx = rm; rm.setDtoSender(sender); From 59e3063145c852d68a883b9e62111abf7cb4258d Mon Sep 17 00:00:00 2001 From: OlivierDelcroix Date: Fri, 17 Apr 2020 14:32:45 +0200 Subject: [PATCH 03/11] improve trace logs --- .../remotese/rm/AbstractRemoteMethodTx.java | 40 +++++++++---------- 1 file changed, 19 insertions(+), 21 deletions(-) diff --git a/java/component/keyple-plugin/remotese/src/main/java/org/eclipse/keyple/plugin/remotese/rm/AbstractRemoteMethodTx.java b/java/component/keyple-plugin/remotese/src/main/java/org/eclipse/keyple/plugin/remotese/rm/AbstractRemoteMethodTx.java index f02cc00ef..1e477197d 100644 --- a/java/component/keyple-plugin/remotese/src/main/java/org/eclipse/keyple/plugin/remotese/rm/AbstractRemoteMethodTx.java +++ b/java/component/keyple-plugin/remotese/src/main/java/org/eclipse/keyple/plugin/remotese/rm/AbstractRemoteMethodTx.java @@ -95,7 +95,7 @@ void setTimeout(long timeout) { * @throws KeypleRemoteException if a problem occurs while sending */ public void send(IRemoteMethodTxCallback callback) throws KeypleRemoteException { - if(logger.isTraceEnabled()){ + if (logger.isTraceEnabled()) { logger.trace("Send asynchronously keypleDto for {}", this); } this.callback = callback; @@ -113,7 +113,7 @@ public void send(IRemoteMethodTxCallback callback) throws KeypleRemoteExcepti */ final public T execute(IRemoteMethodTxEngine rmTxEngine) throws KeypleRemoteException { - if(logger.isTraceEnabled()){ + if (logger.isTraceEnabled()) { logger.trace("execute {}", this.toString()); } // register this method to receive response @@ -133,14 +133,15 @@ public void run() { send(new IRemoteMethodTxCallback() { @Override public void get(T response, KeypleRemoteException exception) { - if(logger.isTraceEnabled()){ + if (logger.isTraceEnabled()) { logger.trace("Release lock of {}", thisInstance.toString()); } lock.countDown(); } }); } catch (KeypleRemoteException e) { - logger.error("Exception {} while sending Dto {} for {}", e.getMessage(), thisInstance); + logger.error("Exception {} while sending Dto {} for {}", e.getMessage(), + thisInstance); thisInstance.remoteException = e; lock.countDown(); } @@ -150,16 +151,16 @@ public void get(T response, KeypleRemoteException exception) { try { lock = new CountDownLatch(1); asyncSend.start(); - if(logger.isTraceEnabled()){ - logger.trace("Lock thread for {}",this.toString()); + if (logger.isTraceEnabled()) { + logger.trace("Lock thread for {}", this.toString()); } // lock until response is received boolean responseReceived = lock.await(timeout, TimeUnit.MILLISECONDS); if (responseReceived) { - if(logger.isTraceEnabled()){ - logger.trace("Unlock thread for {}",this.toString()); + if (logger.isTraceEnabled()) { + logger.trace("Unlock thread for {}", this.toString()); } if (this.remoteException != null) { throw remoteException; @@ -171,13 +172,14 @@ public void get(T response, KeypleRemoteException exception) { * timeout, no answer has been received */ throw new KeypleRemoteException( - "Waiting time elapsed, no answer received from the other node for " + this.toString()); + "Waiting time elapsed, no answer received from the other node for " + + this.toString()); } } catch (InterruptedException e) { throw new IllegalStateException( - "Thread locking has encounterd an exception with "+ this.toString(), e); + "Thread locking has encounterd an exception with " + this.toString(), e); } } @@ -187,8 +189,8 @@ public void get(T response, KeypleRemoteException exception) { * @param keypleDto */ void setResponse(KeypleDto keypleDto) { - if(logger.isTraceEnabled()){ - logger.trace("Response received {} for {}",keypleDto, this.toString()); + if (logger.isTraceEnabled()) { + logger.trace("Response received {} for {}", keypleDto, this.toString()); } try { this.response = parseResponse(keypleDto); @@ -218,14 +220,10 @@ public void setRegistered(Boolean registered) { @Override public String toString() { - return "AbstractRemoteMethodTx{" + - "sessionId='" + sessionId + '\'' + - ", methodName='" + getMethodName() + '\'' + - ", nativeReaderName='" + nativeReaderName + '\'' + - ", virtualReaderName='" + virtualReaderName + '\'' + - ", targetNodeId='" + targetNodeId + '\'' + - ", requesterNodeId='" + requesterNodeId + '\'' + - ", id='" + id + '\'' + - '}'; + return "AbstractRemoteMethodTx{" + "sessionId='" + sessionId + '\'' + ", methodName='" + + getMethodName() + '\'' + ", nativeReaderName='" + nativeReaderName + '\'' + + ", virtualReaderName='" + virtualReaderName + '\'' + ", targetNodeId='" + + targetNodeId + '\'' + ", requesterNodeId='" + requesterNodeId + '\'' + ", id='" + + id + '\'' + '}'; } } From fdbf3db0d56fd73070345daf13298f701dbe343b Mon Sep 17 00:00:00 2001 From: OlivierDelcroix Date: Fri, 17 Apr 2020 14:13:46 +0200 Subject: [PATCH 04/11] improve trace logs --- .../remotese/rm/AbstractRemoteMethodTx.java | 48 ++++++++++++++----- 1 file changed, 36 insertions(+), 12 deletions(-) diff --git a/java/component/keyple-plugin/remotese/src/main/java/org/eclipse/keyple/plugin/remotese/rm/AbstractRemoteMethodTx.java b/java/component/keyple-plugin/remotese/src/main/java/org/eclipse/keyple/plugin/remotese/rm/AbstractRemoteMethodTx.java index 75cc20c16..f02cc00ef 100644 --- a/java/component/keyple-plugin/remotese/src/main/java/org/eclipse/keyple/plugin/remotese/rm/AbstractRemoteMethodTx.java +++ b/java/component/keyple-plugin/remotese/src/main/java/org/eclipse/keyple/plugin/remotese/rm/AbstractRemoteMethodTx.java @@ -95,6 +95,9 @@ void setTimeout(long timeout) { * @throws KeypleRemoteException if a problem occurs while sending */ public void send(IRemoteMethodTxCallback callback) throws KeypleRemoteException { + if(logger.isTraceEnabled()){ + logger.trace("Send asynchronously keypleDto for {}", this); + } this.callback = callback; sender.sendDTO(this.dto()); } @@ -110,12 +113,15 @@ public void send(IRemoteMethodTxCallback callback) throws KeypleRemoteExcepti */ final public T execute(IRemoteMethodTxEngine rmTxEngine) throws KeypleRemoteException { + if(logger.isTraceEnabled()){ + logger.trace("execute {}", this.toString()); + } // register this method to receive response rmTxEngine.register(this); if (!isRegistered) { throw new IllegalStateException( - "RemoteMethodTx#execute() can not be used until RemoteMethod is isRegistered in a RemoteMethodEngine, please call RemoteMethodEngine#register"); + "RemoteMethodTx#execute() can not be used until RemoteMethodTx is registered in a RemoteMethodEngine, please call RemoteMethodEngine#register"); } // logger.debug("Blocking Get {}", this.getClass().getCanonicalName()); final AbstractRemoteMethodTx thisInstance = this; @@ -127,13 +133,14 @@ public void run() { send(new IRemoteMethodTxCallback() { @Override public void get(T response, KeypleRemoteException exception) { - logger.debug("Release lock of rm {} {}", thisInstance.getMethodName(), - thisInstance.id); + if(logger.isTraceEnabled()){ + logger.trace("Release lock of {}", thisInstance.toString()); + } lock.countDown(); } }); } catch (KeypleRemoteException e) { - logger.error("Exception while sending Dto", e); + logger.error("Exception {} while sending Dto {} for {}", e.getMessage(), thisInstance); thisInstance.remoteException = e; lock.countDown(); } @@ -142,14 +149,18 @@ public void get(T response, KeypleRemoteException exception) { try { lock = new CountDownLatch(1); - logger.trace("" + "" + "Set callback on RemoteMethodTx {} {}", - this.getClass().getCanonicalName(), this.hashCode()); asyncSend.start(); - logger.trace("Lock {}, {}", thisInstance.getMethodName(), this.id); + if(logger.isTraceEnabled()){ + logger.trace("Lock thread for {}",this.toString()); + } + + // lock until response is received boolean responseReceived = lock.await(timeout, TimeUnit.MILLISECONDS); if (responseReceived) { - logger.trace("Unlock {}, {}", this.getClass().getCanonicalName(), this.hashCode()); + if(logger.isTraceEnabled()){ + logger.trace("Unlock thread for {}",this.toString()); + } if (this.remoteException != null) { throw remoteException; } else { @@ -160,14 +171,13 @@ public void get(T response, KeypleRemoteException exception) { * timeout, no answer has been received */ throw new KeypleRemoteException( - "Waiting time elapsed, no answer received from the other node for method " - + this.getClass().getCanonicalName()); + "Waiting time elapsed, no answer received from the other node for " + this.toString()); } } catch (InterruptedException e) { throw new IllegalStateException( - "Thread locking in blocking transmitSet has encountered an exception", e); + "Thread locking has encounterd an exception with "+ this.toString(), e); } } @@ -177,6 +187,9 @@ public void get(T response, KeypleRemoteException exception) { * @param keypleDto */ void setResponse(KeypleDto keypleDto) { + if(logger.isTraceEnabled()){ + logger.trace("Response received {} for {}",keypleDto, this.toString()); + } try { this.response = parseResponse(keypleDto); this.callback.get(response, null); @@ -203,5 +216,16 @@ public void setRegistered(Boolean registered) { protected abstract KeypleDto dto(); - + @Override + public String toString() { + return "AbstractRemoteMethodTx{" + + "sessionId='" + sessionId + '\'' + + ", methodName='" + getMethodName() + '\'' + + ", nativeReaderName='" + nativeReaderName + '\'' + + ", virtualReaderName='" + virtualReaderName + '\'' + + ", targetNodeId='" + targetNodeId + '\'' + + ", requesterNodeId='" + requesterNodeId + '\'' + + ", id='" + id + '\'' + + '}'; + } } From fa5d1626018a883e9a40ccf53f7e4000a365e642 Mon Sep 17 00:00:00 2001 From: OlivierDelcroix Date: Fri, 17 Apr 2020 14:31:59 +0200 Subject: [PATCH 05/11] fix NPE --- .../remotese/rm/RemoteMethodTxEngine.java | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/java/component/keyple-plugin/remotese/src/main/java/org/eclipse/keyple/plugin/remotese/rm/RemoteMethodTxEngine.java b/java/component/keyple-plugin/remotese/src/main/java/org/eclipse/keyple/plugin/remotese/rm/RemoteMethodTxEngine.java index ad4f427c9..e9375375c 100644 --- a/java/component/keyple-plugin/remotese/src/main/java/org/eclipse/keyple/plugin/remotese/rm/RemoteMethodTxEngine.java +++ b/java/component/keyple-plugin/remotese/src/main/java/org/eclipse/keyple/plugin/remotese/rm/RemoteMethodTxEngine.java @@ -76,19 +76,28 @@ public TransportDto onDTO(TransportDto message) { */ if (remoteMethodTx == null) { /* - * Should not happen, response received does not match a request. Ignore it + * Response received does not match a request. Ignore it */ logger.error( "RemoteMethodTxEngine receives a KeypleDto response but no remoteMethodTx are defined : " + keypleDto); + + } else { + + /* + * Set keypleDto as a response to the remote method Tx (request) + */ + remoteMethodTx.setResponse(keypleDto); } - // only one operation is allowed at the time - remoteMethodTx.setResponse(keypleDto); + /* + * init remote engine to receive a new request + */ // re init remoteMethod remoteMethodTx = null; + // no dto should be sent back return message.nextTransportDTO(KeypleDtoHelper.NoResponse(keypleDto.getId())); } @@ -99,7 +108,9 @@ public TransportDto onDTO(TransportDto message) { */ @Override public void register(final AbstractRemoteMethodTx rm) { - logger.debug("Register rm to engine : {} {}", rm.getMethodName(), rm.id); + if (logger.isTraceEnabled()) { + logger.trace("Register RemoteMethod to engine : {} ", rm.id); + } rm.setRegistered(true); remoteMethodTx = rm; rm.setDtoSender(sender); From fe8cf736ccbafeebddca5f49d588fbeb90d0b77c Mon Sep 17 00:00:00 2001 From: OlivierDelcroix Date: Fri, 17 Apr 2020 14:32:45 +0200 Subject: [PATCH 06/11] improve trace logs --- .../remotese/rm/AbstractRemoteMethodTx.java | 40 +++++++++---------- 1 file changed, 19 insertions(+), 21 deletions(-) diff --git a/java/component/keyple-plugin/remotese/src/main/java/org/eclipse/keyple/plugin/remotese/rm/AbstractRemoteMethodTx.java b/java/component/keyple-plugin/remotese/src/main/java/org/eclipse/keyple/plugin/remotese/rm/AbstractRemoteMethodTx.java index f02cc00ef..1e477197d 100644 --- a/java/component/keyple-plugin/remotese/src/main/java/org/eclipse/keyple/plugin/remotese/rm/AbstractRemoteMethodTx.java +++ b/java/component/keyple-plugin/remotese/src/main/java/org/eclipse/keyple/plugin/remotese/rm/AbstractRemoteMethodTx.java @@ -95,7 +95,7 @@ void setTimeout(long timeout) { * @throws KeypleRemoteException if a problem occurs while sending */ public void send(IRemoteMethodTxCallback callback) throws KeypleRemoteException { - if(logger.isTraceEnabled()){ + if (logger.isTraceEnabled()) { logger.trace("Send asynchronously keypleDto for {}", this); } this.callback = callback; @@ -113,7 +113,7 @@ public void send(IRemoteMethodTxCallback callback) throws KeypleRemoteExcepti */ final public T execute(IRemoteMethodTxEngine rmTxEngine) throws KeypleRemoteException { - if(logger.isTraceEnabled()){ + if (logger.isTraceEnabled()) { logger.trace("execute {}", this.toString()); } // register this method to receive response @@ -133,14 +133,15 @@ public void run() { send(new IRemoteMethodTxCallback() { @Override public void get(T response, KeypleRemoteException exception) { - if(logger.isTraceEnabled()){ + if (logger.isTraceEnabled()) { logger.trace("Release lock of {}", thisInstance.toString()); } lock.countDown(); } }); } catch (KeypleRemoteException e) { - logger.error("Exception {} while sending Dto {} for {}", e.getMessage(), thisInstance); + logger.error("Exception {} while sending Dto {} for {}", e.getMessage(), + thisInstance); thisInstance.remoteException = e; lock.countDown(); } @@ -150,16 +151,16 @@ public void get(T response, KeypleRemoteException exception) { try { lock = new CountDownLatch(1); asyncSend.start(); - if(logger.isTraceEnabled()){ - logger.trace("Lock thread for {}",this.toString()); + if (logger.isTraceEnabled()) { + logger.trace("Lock thread for {}", this.toString()); } // lock until response is received boolean responseReceived = lock.await(timeout, TimeUnit.MILLISECONDS); if (responseReceived) { - if(logger.isTraceEnabled()){ - logger.trace("Unlock thread for {}",this.toString()); + if (logger.isTraceEnabled()) { + logger.trace("Unlock thread for {}", this.toString()); } if (this.remoteException != null) { throw remoteException; @@ -171,13 +172,14 @@ public void get(T response, KeypleRemoteException exception) { * timeout, no answer has been received */ throw new KeypleRemoteException( - "Waiting time elapsed, no answer received from the other node for " + this.toString()); + "Waiting time elapsed, no answer received from the other node for " + + this.toString()); } } catch (InterruptedException e) { throw new IllegalStateException( - "Thread locking has encounterd an exception with "+ this.toString(), e); + "Thread locking has encounterd an exception with " + this.toString(), e); } } @@ -187,8 +189,8 @@ public void get(T response, KeypleRemoteException exception) { * @param keypleDto */ void setResponse(KeypleDto keypleDto) { - if(logger.isTraceEnabled()){ - logger.trace("Response received {} for {}",keypleDto, this.toString()); + if (logger.isTraceEnabled()) { + logger.trace("Response received {} for {}", keypleDto, this.toString()); } try { this.response = parseResponse(keypleDto); @@ -218,14 +220,10 @@ public void setRegistered(Boolean registered) { @Override public String toString() { - return "AbstractRemoteMethodTx{" + - "sessionId='" + sessionId + '\'' + - ", methodName='" + getMethodName() + '\'' + - ", nativeReaderName='" + nativeReaderName + '\'' + - ", virtualReaderName='" + virtualReaderName + '\'' + - ", targetNodeId='" + targetNodeId + '\'' + - ", requesterNodeId='" + requesterNodeId + '\'' + - ", id='" + id + '\'' + - '}'; + return "AbstractRemoteMethodTx{" + "sessionId='" + sessionId + '\'' + ", methodName='" + + getMethodName() + '\'' + ", nativeReaderName='" + nativeReaderName + '\'' + + ", virtualReaderName='" + virtualReaderName + '\'' + ", targetNodeId='" + + targetNodeId + '\'' + ", requesterNodeId='" + requesterNodeId + '\'' + ", id='" + + id + '\'' + '}'; } } From 18bda52dde645f47285d4b857835df1380467cbb Mon Sep 17 00:00:00 2001 From: Jean-Pierre Fortune Date: Fri, 17 Apr 2020 18:57:32 +0200 Subject: [PATCH 07/11] feat: KEYP-187 add allocation failure exceptions add CalypsoNoSamResourceAvailableException and KeypleAllocationReaderException --- ...alypsoNoSamResourceAvailableException.java | 28 +++++++++++++++ .../KeypleAllocationReaderException.java | 35 +++++++++++++++++++ 2 files changed, 63 insertions(+) create mode 100644 java/component/keyple-calypso/src/main/java/org/eclipse/keyple/calypso/exception/CalypsoNoSamResourceAvailableException.java create mode 100644 java/component/keyple-core/src/main/java/org/eclipse/keyple/core/seproxy/exception/KeypleAllocationReaderException.java diff --git a/java/component/keyple-calypso/src/main/java/org/eclipse/keyple/calypso/exception/CalypsoNoSamResourceAvailableException.java b/java/component/keyple-calypso/src/main/java/org/eclipse/keyple/calypso/exception/CalypsoNoSamResourceAvailableException.java new file mode 100644 index 000000000..bd3d9d51a --- /dev/null +++ b/java/component/keyple-calypso/src/main/java/org/eclipse/keyple/calypso/exception/CalypsoNoSamResourceAvailableException.java @@ -0,0 +1,28 @@ +/******************************************************************************** + * Copyright (c) 2020 Calypso Networks Association https://www.calypsonet-asso.org/ + * + * See the NOTICE file(s) distributed with this work for additional information regarding copyright + * ownership. + * + * This program and the accompanying materials are made available under the terms of the Eclipse + * Public License 2.0 which is available at http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + ********************************************************************************/ +package org.eclipse.keyple.calypso.exception; + +import org.eclipse.keyple.core.seproxy.exception.KeypleBaseException; + +/** + * The exception {@code CalypsoNoSamResourceAvailableException} indicates that there are no SAM + * resources available. + */ +public class CalypsoNoSamResourceAvailableException extends KeypleBaseException { + + /** + * @param message the message to identify the exception context + */ + public CalypsoNoSamResourceAvailableException(String message) { + super(message); + } +} diff --git a/java/component/keyple-core/src/main/java/org/eclipse/keyple/core/seproxy/exception/KeypleAllocationReaderException.java b/java/component/keyple-core/src/main/java/org/eclipse/keyple/core/seproxy/exception/KeypleAllocationReaderException.java new file mode 100644 index 000000000..c72997f7d --- /dev/null +++ b/java/component/keyple-core/src/main/java/org/eclipse/keyple/core/seproxy/exception/KeypleAllocationReaderException.java @@ -0,0 +1,35 @@ +/******************************************************************************** + * Copyright (c) 2019 Calypso Networks Association https://www.calypsonet-asso.org/ + * + * See the NOTICE file(s) distributed with this work for additional information regarding copyright + * ownership. + * + * This program and the accompanying materials are made available under the terms of the Eclipse + * Public License 2.0 which is available at http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + ********************************************************************************/ +package org.eclipse.keyple.core.seproxy.exception; + +/** + * The exception {@code KeypleAllocationReaderException} indicates that a reader allocation failed. + */ +public class KeypleAllocationReaderException extends KeypleBaseException { + + /** + * @param message the message to identify the exception context + */ + public KeypleAllocationReaderException(String message) { + super(message); + } + + /** + * Encapsulates a lower level reader exception + * + * @param message message to identify the exception context + * @param cause the cause + */ + public KeypleAllocationReaderException(String message, Throwable cause) { + super(message, cause); + } +} From 1d2ee187e2182951d554a3d59d6e16111a42681f Mon Sep 17 00:00:00 2001 From: Jean-Pierre Fortune Date: Fri, 17 Apr 2020 19:01:05 +0200 Subject: [PATCH 08/11] feat: KEYP-187,189 update ReaderPoolPlugin and SamResourceManager - add CalypsoNoSamResourceAvailableException and KeypleAllocationReaderException management - make MAX_BLOCKING_TIME configurable through with a new constructor --- .../transaction/SamResourceManager.java | 51 ++++++++++++++----- .../keyple/core/seproxy/ReaderPoolPlugin.java | 4 +- 2 files changed, 41 insertions(+), 14 deletions(-) diff --git a/java/component/keyple-calypso/src/main/java/org/eclipse/keyple/calypso/transaction/SamResourceManager.java b/java/component/keyple-calypso/src/main/java/org/eclipse/keyple/calypso/transaction/SamResourceManager.java index 7e1c74ed4..311c0d0ab 100644 --- a/java/component/keyple-calypso/src/main/java/org/eclipse/keyple/calypso/transaction/SamResourceManager.java +++ b/java/component/keyple-calypso/src/main/java/org/eclipse/keyple/calypso/transaction/SamResourceManager.java @@ -14,6 +14,7 @@ import static org.eclipse.keyple.calypso.command.sam.SamRevision.AUTO; import java.util.*; import java.util.regex.Pattern; +import org.eclipse.keyple.calypso.exception.CalypsoNoSamResourceAvailableException; import org.eclipse.keyple.core.selection.SeSelection; import org.eclipse.keyple.core.selection.SelectionsResult; import org.eclipse.keyple.core.seproxy.*; @@ -40,8 +41,9 @@ public enum AllocationMode { BLOCKING, NON_BLOCKING } - /* the maximum time (in tenths of a second) during which the BLOCKING mode will wait */ - private final static int MAX_BLOCKING_TIME = 1000; // 10 sec + /* the default maximum time (in milliseconds) during which the BLOCKING mode will wait */ + private final static int MAX_BLOCKING_TIME = 1000; // 1 sec + private final int maxBlockingTime; private final ReaderPlugin samReaderPlugin; private final List localSamResources = new ArrayList(); private final boolean dynamicAllocationPlugin; @@ -56,10 +58,13 @@ public enum AllocationMode { * @param samReaderPlugin the plugin through which SAM readers are accessible * @param samReaderFilter the regular expression defining how to identify SAM readers among * others. - * @throws KeypleReaderException throw if an error occurs while getting the readers list. + * @param maxBlockingTime the maximum duration for which the allocateSamResource method will + * attempt to allocate a new reader by retrying (in milliseconds) + * @throws KeypleReaderException thrown if an error occurs while getting the readers list. + * @Since 0.8.1 */ - public SamResourceManager(ReaderPlugin samReaderPlugin, String samReaderFilter) - throws KeypleReaderException { + public SamResourceManager(ReaderPlugin samReaderPlugin, String samReaderFilter, + int maxBlockingTime) throws KeypleReaderException { this.samReaderPlugin = samReaderPlugin; if (samReaderPlugin instanceof ReaderPoolPlugin) { logger.info("Create SAM resource manager from reader pool plugin: {}", @@ -95,6 +100,20 @@ public SamResourceManager(ReaderPlugin samReaderPlugin, String samReaderFilter) } } } + this.maxBlockingTime = maxBlockingTime; + } + + /** + * Alternate constructor with default max blocking time value + * + * @param samReaderPlugin the plugin through which SAM readers are accessible + * @param samReaderFilter the regular expression defining how to identify SAM readers among + * others. + * @throws KeypleReaderException thrown if an error occurs while getting the readers list. + */ + public SamResourceManager(ReaderPlugin samReaderPlugin, String samReaderFilter) + throws KeypleReaderException { + this(samReaderPlugin, samReaderFilter, MAX_BLOCKING_TIME); } /** @@ -144,17 +163,24 @@ private SamResource createSamResource(SeReader samReader) throws KeypleReaderExc * @param samIdentifier the targeted SAM identifier * @return a SAM resource * @throws KeypleReaderException if a reader error occurs + * @throws CalypsoNoSamResourceAvailableException if the reader allocation failed */ public SamResource allocateSamResource(AllocationMode allocationMode, - SamIdentifier samIdentifier) throws KeypleReaderException { - long maxBlockingDate = System.currentTimeMillis() + MAX_BLOCKING_TIME; + SamIdentifier samIdentifier) + throws KeypleReaderException, CalypsoNoSamResourceAvailableException { + long maxBlockingDate = System.currentTimeMillis() + maxBlockingTime; boolean noSamResourceLogged = false; logger.debug("Allocating SAM reader channel..."); while (true) { if (dynamicAllocationPlugin) { // virtually infinite number of readers - SeReader samReader = ((ReaderPoolPlugin) samReaderPlugin) - .allocateReader(samIdentifier.getGroupReference()); + SeReader samReader = null; + try { + samReader = ((ReaderPoolPlugin) samReaderPlugin) + .allocateReader(samIdentifier.getGroupReference()); + } catch (KeypleAllocationReaderException e) { + throw new CalypsoNoSamResourceAvailableException(e.getMessage()); + } if (samReader != null) { SamResource samResource = createSamResource(samReader); logger.debug("Allocation succeeded. SAM resource created."); @@ -191,13 +217,12 @@ public SamResource allocateSamResource(AllocationMode allocationMode, logger.error("Interrupt exception in Thread.sleep."); } if (System.currentTimeMillis() >= maxBlockingDate) { - logger.error("The allocation process failed. Timeout {} sec exceeded .", - (MAX_BLOCKING_TIME / 100.0)); - return null; + throw new CalypsoNoSamResourceAvailableException( + "The allocation process has timed out."); } } } - return null; + throw new CalypsoNoSamResourceAvailableException("The allocation process has failed."); } /** diff --git a/java/component/keyple-core/src/main/java/org/eclipse/keyple/core/seproxy/ReaderPoolPlugin.java b/java/component/keyple-core/src/main/java/org/eclipse/keyple/core/seproxy/ReaderPoolPlugin.java index 3032b81e2..1836b2a00 100644 --- a/java/component/keyple-core/src/main/java/org/eclipse/keyple/core/seproxy/ReaderPoolPlugin.java +++ b/java/component/keyple-core/src/main/java/org/eclipse/keyple/core/seproxy/ReaderPoolPlugin.java @@ -12,6 +12,7 @@ package org.eclipse.keyple.core.seproxy; import java.util.SortedSet; +import org.eclipse.keyple.core.seproxy.exception.KeypleAllocationReaderException; /** * The ReaderPoolPlugin interface provides methods to handle the access to an undefined number of @@ -42,8 +43,9 @@ public interface ReaderPoolPlugin extends ReaderPlugin { * @param groupReference the reference of the group to which the reader belongs (may be null * depending on the implementation made) * @return a SeReader object + * @throws KeypleAllocationReaderException if the allocation failed */ - SeReader allocateReader(String groupReference); + SeReader allocateReader(String groupReference) throws KeypleAllocationReaderException; /** * Releases a SeReader previously allocated with allocateReader. From ef0c02b40e8f7d2d40dc6ad421b8e3004c516cba Mon Sep 17 00:00:00 2001 From: Jean-Pierre Fortune Date: Fri, 17 Apr 2020 19:01:57 +0200 Subject: [PATCH 09/11] bug: KEYP-187 handle allocation exception in remote se plugin --- .../remotese/nativese/method/RmPoolAllocateExecutor.java | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/java/component/keyple-plugin/remotese/src/main/java/org/eclipse/keyple/plugin/remotese/nativese/method/RmPoolAllocateExecutor.java b/java/component/keyple-plugin/remotese/src/main/java/org/eclipse/keyple/plugin/remotese/nativese/method/RmPoolAllocateExecutor.java index 1ca9eb3e4..27b3425ec 100644 --- a/java/component/keyple-plugin/remotese/src/main/java/org/eclipse/keyple/plugin/remotese/nativese/method/RmPoolAllocateExecutor.java +++ b/java/component/keyple-plugin/remotese/src/main/java/org/eclipse/keyple/plugin/remotese/nativese/method/RmPoolAllocateExecutor.java @@ -13,6 +13,7 @@ import org.eclipse.keyple.core.seproxy.ReaderPoolPlugin; import org.eclipse.keyple.core.seproxy.SeReader; +import org.eclipse.keyple.core.seproxy.exception.KeypleAllocationReaderException; import org.eclipse.keyple.core.seproxy.message.SeResponse; import org.eclipse.keyple.plugin.remotese.rm.IRemoteMethodExecutor; import org.eclipse.keyple.plugin.remotese.rm.RemoteMethodName; @@ -47,7 +48,13 @@ public TransportDto execute(TransportDto transportDto) { String groupReference = body.get("groupReference").getAsString(); // Execute Remote Method - SeReader seReader = poolPlugin.allocateReader(groupReference); + SeReader seReader = null; + try { + seReader = poolPlugin.allocateReader(groupReference); + } catch (KeypleAllocationReaderException e) { + // TODO Handle this exception + e.printStackTrace(); + } // Build Response JsonObject bodyResp = new JsonObject(); From 9d07fb8b09139d2815a45bea824458318336619b Mon Sep 17 00:00:00 2001 From: Jean-Pierre Fortune Date: Fri, 17 Apr 2020 21:23:53 +0200 Subject: [PATCH 10/11] bug: KEYP-192 fix Javadoc tag issue --- .../eclipse/keyple/calypso/transaction/SamResourceManager.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java/component/keyple-calypso/src/main/java/org/eclipse/keyple/calypso/transaction/SamResourceManager.java b/java/component/keyple-calypso/src/main/java/org/eclipse/keyple/calypso/transaction/SamResourceManager.java index 311c0d0ab..b4846bb6c 100644 --- a/java/component/keyple-calypso/src/main/java/org/eclipse/keyple/calypso/transaction/SamResourceManager.java +++ b/java/component/keyple-calypso/src/main/java/org/eclipse/keyple/calypso/transaction/SamResourceManager.java @@ -61,7 +61,7 @@ public enum AllocationMode { * @param maxBlockingTime the maximum duration for which the allocateSamResource method will * attempt to allocate a new reader by retrying (in milliseconds) * @throws KeypleReaderException thrown if an error occurs while getting the readers list. - * @Since 0.8.1 + * @since 0.8.1 */ public SamResourceManager(ReaderPlugin samReaderPlugin, String samReaderFilter, int maxBlockingTime) throws KeypleReaderException { From a8f0c6e44d6913c25e29b395542ee913d0d8a94d Mon Sep 17 00:00:00 2001 From: OlivierDelcroix Date: Mon, 20 Apr 2020 14:55:55 +0200 Subject: [PATCH 11/11] bug/keyp-187 : improve use of KeypleAllocationReaderException - handle KeypleAllocationReaderException in RemoteSePoolPlugin - handle KeypleAllocationReaderException in StubPoolPlugin --- .../CalypsoNoSamResourceAvailableException.java | 7 +++++++ .../calypso/transaction/SamResourceManager.java | 2 +- .../nativese/method/RmPoolAllocateExecutor.java | 6 ++++-- .../remotese/pluginse/RemoteSePoolPluginImpl.java | 8 +++++--- .../keyple/plugin/stub/StubPoolPluginImpl.java | 8 +++++--- .../keyple/plugin/stub/StubPoolPluginTest.java | 14 ++++++++------ 6 files changed, 30 insertions(+), 15 deletions(-) diff --git a/java/component/keyple-calypso/src/main/java/org/eclipse/keyple/calypso/exception/CalypsoNoSamResourceAvailableException.java b/java/component/keyple-calypso/src/main/java/org/eclipse/keyple/calypso/exception/CalypsoNoSamResourceAvailableException.java index bd3d9d51a..86f4901cd 100644 --- a/java/component/keyple-calypso/src/main/java/org/eclipse/keyple/calypso/exception/CalypsoNoSamResourceAvailableException.java +++ b/java/component/keyple-calypso/src/main/java/org/eclipse/keyple/calypso/exception/CalypsoNoSamResourceAvailableException.java @@ -25,4 +25,11 @@ public class CalypsoNoSamResourceAvailableException extends KeypleBaseException public CalypsoNoSamResourceAvailableException(String message) { super(message); } + + /** + * @param message the message to identify the exception context + */ + public CalypsoNoSamResourceAvailableException(String message, Throwable t) { + super(message, t); + } } diff --git a/java/component/keyple-calypso/src/main/java/org/eclipse/keyple/calypso/transaction/SamResourceManager.java b/java/component/keyple-calypso/src/main/java/org/eclipse/keyple/calypso/transaction/SamResourceManager.java index b4846bb6c..0cca9edfc 100644 --- a/java/component/keyple-calypso/src/main/java/org/eclipse/keyple/calypso/transaction/SamResourceManager.java +++ b/java/component/keyple-calypso/src/main/java/org/eclipse/keyple/calypso/transaction/SamResourceManager.java @@ -179,7 +179,7 @@ public SamResource allocateSamResource(AllocationMode allocationMode, samReader = ((ReaderPoolPlugin) samReaderPlugin) .allocateReader(samIdentifier.getGroupReference()); } catch (KeypleAllocationReaderException e) { - throw new CalypsoNoSamResourceAvailableException(e.getMessage()); + throw new CalypsoNoSamResourceAvailableException(e.getMessage(), e); } if (samReader != null) { SamResource samResource = createSamResource(samReader); diff --git a/java/component/keyple-plugin/remotese/src/main/java/org/eclipse/keyple/plugin/remotese/nativese/method/RmPoolAllocateExecutor.java b/java/component/keyple-plugin/remotese/src/main/java/org/eclipse/keyple/plugin/remotese/nativese/method/RmPoolAllocateExecutor.java index 27b3425ec..6885495e7 100644 --- a/java/component/keyple-plugin/remotese/src/main/java/org/eclipse/keyple/plugin/remotese/nativese/method/RmPoolAllocateExecutor.java +++ b/java/component/keyple-plugin/remotese/src/main/java/org/eclipse/keyple/plugin/remotese/nativese/method/RmPoolAllocateExecutor.java @@ -52,8 +52,10 @@ public TransportDto execute(TransportDto transportDto) { try { seReader = poolPlugin.allocateReader(groupReference); } catch (KeypleAllocationReaderException e) { - // TODO Handle this exception - e.printStackTrace(); + // if an exception occurs, send it into a keypleDto to the Master + return transportDto.nextTransportDTO(KeypleDtoHelper.ExceptionDTO( + getMethodName().getName(), e, null, null, null, keypleDto.getTargetNodeId(), + keypleDto.getRequesterNodeId(), keypleDto.getId())); } // Build Response diff --git a/java/component/keyple-plugin/remotese/src/main/java/org/eclipse/keyple/plugin/remotese/pluginse/RemoteSePoolPluginImpl.java b/java/component/keyple-plugin/remotese/src/main/java/org/eclipse/keyple/plugin/remotese/pluginse/RemoteSePoolPluginImpl.java index 02a89f55f..b330ba1ff 100644 --- a/java/component/keyple-plugin/remotese/src/main/java/org/eclipse/keyple/plugin/remotese/pluginse/RemoteSePoolPluginImpl.java +++ b/java/component/keyple-plugin/remotese/src/main/java/org/eclipse/keyple/plugin/remotese/pluginse/RemoteSePoolPluginImpl.java @@ -13,6 +13,7 @@ import java.util.SortedSet; import org.eclipse.keyple.core.seproxy.SeReader; +import org.eclipse.keyple.core.seproxy.exception.KeypleAllocationReaderException; import org.eclipse.keyple.plugin.remotese.exception.KeypleRemoteException; import org.eclipse.keyple.plugin.remotese.rm.RemoteMethodTxPoolEngine; import org.eclipse.keyple.plugin.remotese.transport.DtoSender; @@ -57,7 +58,7 @@ public SortedSet getReaderGroupReferences() { } @Override - public SeReader allocateReader(String groupReference) { + public SeReader allocateReader(String groupReference) throws KeypleAllocationReaderException { if (slaveNodeId == null) { throw new IllegalStateException( @@ -71,7 +72,8 @@ public SeReader allocateReader(String groupReference) { // blocking call return allocate.execute(rmTxEngine); } catch (KeypleRemoteException e) { - return null;// todo throw exception here + throw new KeypleAllocationReaderException( + "Reader Allocation failed for group reference: " + groupReference, e); } } @@ -92,7 +94,7 @@ public void releaseReader(SeReader seReader) { VirtualReaderImpl virtualReader = (VirtualReaderImpl) seReader; - // call remote method for allocateReader + // call remote method for releaseReader RmPoolReleaseTx releaseTx = new RmPoolReleaseTx(virtualReader.getNativeReaderName(), virtualReader.getName(), this, this.dtoSender, slaveNodeId, dtoSender.getNodeId()); diff --git a/java/component/keyple-plugin/stub/src/main/java/org/eclipse/keyple/plugin/stub/StubPoolPluginImpl.java b/java/component/keyple-plugin/stub/src/main/java/org/eclipse/keyple/plugin/stub/StubPoolPluginImpl.java index 2422ead4a..6eca2aa68 100644 --- a/java/component/keyple-plugin/stub/src/main/java/org/eclipse/keyple/plugin/stub/StubPoolPluginImpl.java +++ b/java/component/keyple-plugin/stub/src/main/java/org/eclipse/keyple/plugin/stub/StubPoolPluginImpl.java @@ -15,6 +15,7 @@ import org.eclipse.keyple.core.seproxy.ReaderPlugin; import org.eclipse.keyple.core.seproxy.ReaderPoolPlugin; import org.eclipse.keyple.core.seproxy.SeReader; +import org.eclipse.keyple.core.seproxy.exception.KeypleAllocationReaderException; import org.eclipse.keyple.core.seproxy.exception.KeypleBaseException; import org.eclipse.keyple.core.seproxy.exception.KeypleReaderException; import org.eclipse.keyple.core.seproxy.exception.KeypleReaderNotFoundException; @@ -103,18 +104,19 @@ public void unplugStubPoolReader(String groupReference) { * @return seReader if available, null otherwise */ @Override - public SeReader allocateReader(String groupReference) { + public SeReader allocateReader(String groupReference) throws KeypleAllocationReaderException { // find the reader in the readerPool StubReaderImpl seReader = readerPool.get(groupReference); // check if the reader is available if (seReader == null || allocatedReader.containsKey(seReader.getName())) { - return null; + throw new KeypleAllocationReaderException( + "Impossible to allocate a reader for groupReference : " + groupReference + + ". Has the reader being plugged to this referenceGroup?"); } else { allocatedReader.put(seReader.getName(), groupReference); return seReader; } - } /** diff --git a/java/component/keyple-plugin/stub/src/test/java/org/eclipse/keyple/plugin/stub/StubPoolPluginTest.java b/java/component/keyple-plugin/stub/src/test/java/org/eclipse/keyple/plugin/stub/StubPoolPluginTest.java index 907ffc6b9..2e5b1f8d0 100644 --- a/java/component/keyple-plugin/stub/src/test/java/org/eclipse/keyple/plugin/stub/StubPoolPluginTest.java +++ b/java/component/keyple-plugin/stub/src/test/java/org/eclipse/keyple/plugin/stub/StubPoolPluginTest.java @@ -12,6 +12,7 @@ package org.eclipse.keyple.plugin.stub; import org.eclipse.keyple.core.seproxy.SeReader; +import org.eclipse.keyple.core.seproxy.exception.KeypleAllocationReaderException; import org.eclipse.keyple.core.seproxy.exception.KeyplePluginNotFoundException; import org.eclipse.keyple.core.seproxy.exception.KeypleReaderException; import org.junit.*; @@ -83,7 +84,8 @@ public void unplugStubPoolReader_success() throws InterruptedException, KeypleRe * Allocate one reader */ @Test - public void allocate_success() throws InterruptedException, KeypleReaderException { + public void allocate_success() + throws InterruptedException, KeypleReaderException, KeypleAllocationReaderException { // init stubPoolPlugin StubPoolPluginImpl stubPoolPlugin = (StubPoolPluginImpl) new StubPoolPluginFactory(POOL_PLUGIN_NAME) @@ -108,8 +110,9 @@ public void allocate_success() throws InterruptedException, KeypleReaderExceptio /** * Allocate twice the same reader, it does throw any error as no concurrency is managed */ - @Test - public void allocate_twice() throws InterruptedException, KeypleReaderException { + @Test(expected = KeypleAllocationReaderException.class) + public void allocate_twice() + throws InterruptedException, KeypleReaderException, KeypleAllocationReaderException { // init stubPoolPlugin StubPoolPluginImpl stubPoolPlugin = (StubPoolPluginImpl) new StubPoolPluginFactory(POOL_PLUGIN_NAME) @@ -123,15 +126,14 @@ public void allocate_twice() throws InterruptedException, KeypleReaderException SeReader seReader = stubPoolPlugin.allocateReader("group1"); SeReader seReader2 = stubPoolPlugin.allocateReader("group1"); - // check reader has been allocated twice - Assert.assertNull(seReader2); } /** * Release one reader */ @Test - public void release_success() throws InterruptedException, KeypleReaderException { + public void release_success() + throws InterruptedException, KeypleReaderException, KeypleAllocationReaderException { // init stubPoolPlugin StubPoolPluginImpl stubPoolPlugin = (StubPoolPluginImpl) new StubPoolPluginFactory(POOL_PLUGIN_NAME)