Refactors VABInterfaces and Providers to use ProviderExceptions
Refactors VABBaSyxTCPInterface and VABHTTPInterface to handle ProviderExceptions
Refactors JSONProvider, AASAggregationProvider and DirectoryModelProvider to use ProviderExceptions
Refactors tests to test new Exception behavior
Change-Id: I7f24a2abb20f4c7e7e3613b7c7f5018759128f3a
Signed-off-by: Maximilian Conradi <maximilian.conradi@iese.fraunhofer.de>
diff --git a/components/basys.components/basyx.components.docker/basyx.components.sqlregistry/src/test/java/org/eclipse/basyx/regression/registry/ITSQLRegistryRaw.java b/components/basys.components/basyx.components.docker/basyx.components.sqlregistry/src/test/java/org/eclipse/basyx/regression/registry/ITSQLRegistryRaw.java
index 53b9609..9f96f53 100644
--- a/components/basys.components/basyx.components.docker/basyx.components.sqlregistry/src/test/java/org/eclipse/basyx/regression/registry/ITSQLRegistryRaw.java
+++ b/components/basys.components/basyx.components.docker/basyx.components.sqlregistry/src/test/java/org/eclipse/basyx/regression/registry/ITSQLRegistryRaw.java
@@ -8,6 +8,8 @@
import java.util.Collection;
import java.util.Map;
+import javax.ws.rs.NotFoundException;
+
import org.eclipse.basyx.aas.metamodel.map.descriptor.AASDescriptor;
import org.eclipse.basyx.aas.metamodel.map.descriptor.ModelUrn;
import org.eclipse.basyx.components.configuration.BaSyxContextConfiguration;
@@ -96,8 +98,12 @@
@After
public void tearDown() throws UnsupportedEncodingException {
// Delete AAS registration
- client.delete(aasUrl1);
- client.delete(aasUrl2);
+ try {
+ client.delete(aasUrl1);
+ } catch(NotFoundException e) {}
+ try {
+ client.delete(aasUrl2);
+ } catch(NotFoundException e) {}
}
/**
@@ -173,7 +179,7 @@
try {
getResult(client.get(aasUrl2));
fail();
- } catch(Exception e) {}
+ } catch(NotFoundException e) {}
// Create new AAS registration
client.post(registryUrl, serializedDescriptor2);
@@ -190,7 +196,7 @@
try {
getResult(client.get(aasUrl2));
fail();
- } catch(Exception e) {}
+ } catch(NotFoundException e) {}
}
/**
diff --git a/sdks/java/basys.sdk/src/main/java/org/eclipse/basyx/aas/aggregator/restapi/AASAggregationProvider.java b/sdks/java/basys.sdk/src/main/java/org/eclipse/basyx/aas/aggregator/restapi/AASAggregationProvider.java
index b000110..142a2f8 100644
--- a/sdks/java/basys.sdk/src/main/java/org/eclipse/basyx/aas/aggregator/restapi/AASAggregationProvider.java
+++ b/sdks/java/basys.sdk/src/main/java/org/eclipse/basyx/aas/aggregator/restapi/AASAggregationProvider.java
@@ -9,6 +9,9 @@
import org.eclipse.basyx.aas.metamodel.map.descriptor.ModelUrn;
import org.eclipse.basyx.submodel.metamodel.api.identifier.IIdentifier;
import org.eclipse.basyx.submodel.metamodel.map.modeltype.ModelType;
+import org.eclipse.basyx.vab.exception.provider.MalformedRequestException;
+import org.eclipse.basyx.vab.exception.provider.ResourceAlreadyExistsException;
+import org.eclipse.basyx.vab.exception.provider.ResourceNotFoundException;
import org.eclipse.basyx.vab.modelprovider.VABPathTools;
import org.eclipse.basyx.vab.modelprovider.api.IModelProvider;
@@ -34,11 +37,12 @@
* prefix)
* @param path
* @return
+ * @throws MalformedRequestException
*/
- private String stripPrefix(String path) {
+ private String stripPrefix(String path) throws MalformedRequestException {
path = VABPathTools.stripSlashes(path);
if (!path.startsWith(PREFIX)) {
- throw new RuntimeException("Path " + path + " not recognized as aggregator path. Has to start with " + PREFIX);
+ throw new MalformedRequestException("Path " + path + " not recognized as aggregator path. Has to start with " + PREFIX);
}
path = path.replace(PREFIX, "");
path = VABPathTools.stripSlashes(path);
@@ -51,13 +55,14 @@
*
* @param value the AAS Map object
* @return an AAS
+ * @throws MalformedRequestException
*/
@SuppressWarnings("unchecked")
- private AssetAdministrationShell createAASFromMap(Object value) {
+ private AssetAdministrationShell createAASFromMap(Object value) throws MalformedRequestException {
//check if the given value is a Map
if(!(value instanceof Map)) {
- throw new RuntimeException("Given newValue is not a Map");
+ throw new MalformedRequestException("Given newValue is not a Map");
}
Map<String, Object> map = (Map<String, Object>) value;
@@ -68,7 +73,7 @@
//have to accept Objects without modeltype information,
//as modeltype is not part of the public metamodel
if(!AssetAdministrationShell.MODELTYPE.equals(type) && type != null) {
- throw new RuntimeException("Given newValue map has not the correct ModelType");
+ throw new MalformedRequestException("Given newValue map has not the correct ModelType");
}
AssetAdministrationShell aas = AssetAdministrationShell.createAsFacade(map);
@@ -90,7 +95,7 @@
//Throw an Exception if the requested aas does not exist
if(aas == null) {
- throw new RuntimeException("Requested aasID '" + path + "' does not exist.");
+ throw new ResourceNotFoundException("Requested aasID '" + path + "' does not exist.");
}
return aas;
}
@@ -109,16 +114,16 @@
ModelUrn identifier = new ModelUrn(path);
if(!aas.getIdentification().getId().equals(path)) {
- throw new RuntimeException("Given aasID and given AAS do not match");
+ throw new MalformedRequestException("Given aasID and given AAS do not match");
}
if(aggregator.getAAS(identifier) == null) {
- throw new RuntimeException("Can not update non existing value '" + path + "'. Try create instead.");
+ throw new ResourceAlreadyExistsException("Can not update non existing value '" + path + "'. Try create instead.");
}
aggregator.updateAAS(aas);
} else {
- throw new RuntimeException("Set with empty path is not supported by aggregator");
+ throw new MalformedRequestException("Set with empty path is not supported by aggregator");
}
}
@@ -132,12 +137,12 @@
if (path.isEmpty()) { // Creating new entry
if(aggregator.getAAS(aas.getIdentification()) != null) {
- throw new RuntimeException("Value '" + path + "' to be created already exists. Try update instead.");
+ throw new ResourceAlreadyExistsException("Value '" + path + "' to be created already exists. Try update instead.");
}
aggregator.createAAS(aas);
} else {
- throw new RuntimeException("Create was called with an unsupported path: " + path);
+ throw new MalformedRequestException("Create was called with an unsupported path: " + path);
}
}
@@ -153,23 +158,23 @@
IIdentifier identifier = new ModelUrn(path);
if(aggregator.getAAS(identifier) == null) {
- throw new RuntimeException("Value '" + path + "' to be deleted does not exists.");
+ throw new ResourceNotFoundException("Value '" + path + "' to be deleted does not exists.");
}
aggregator.deleteAAS(identifier);
} else {
- throw new RuntimeException("Delete with empty path is not supported by registry");
+ throw new MalformedRequestException("Delete with empty path is not supported by registry");
}
}
@Override
public void deleteValue(String path, Object obj) throws Exception {
- throw new RuntimeException("DeleteValue with parameter not supported by aggregator");
+ throw new MalformedRequestException("DeleteValue with parameter not supported by aggregator");
}
@Override
public Object invokeOperation(String path, Object... parameter) throws Exception {
- throw new RuntimeException("Invoke not supported by aggregator");
+ throw new MalformedRequestException("Invoke not supported by aggregator");
}
}
diff --git a/sdks/java/basys.sdk/src/main/java/org/eclipse/basyx/aas/registration/restapi/DirectoryModelProvider.java b/sdks/java/basys.sdk/src/main/java/org/eclipse/basyx/aas/registration/restapi/DirectoryModelProvider.java
index 6dc3165..b48cc90 100644
--- a/sdks/java/basys.sdk/src/main/java/org/eclipse/basyx/aas/registration/restapi/DirectoryModelProvider.java
+++ b/sdks/java/basys.sdk/src/main/java/org/eclipse/basyx/aas/registration/restapi/DirectoryModelProvider.java
@@ -1,5 +1,6 @@
package org.eclipse.basyx.aas.registration.restapi;
+import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.util.Map;
import java.util.Set;
@@ -11,6 +12,10 @@
import org.eclipse.basyx.aas.registration.memory.InMemoryRegistry;
import org.eclipse.basyx.submodel.metamodel.api.identifier.IIdentifier;
import org.eclipse.basyx.submodel.metamodel.map.modeltype.ModelType;
+import org.eclipse.basyx.vab.exception.provider.MalformedRequestException;
+import org.eclipse.basyx.vab.exception.provider.ProviderException;
+import org.eclipse.basyx.vab.exception.provider.ResourceAlreadyExistsException;
+import org.eclipse.basyx.vab.exception.provider.ResourceNotFoundException;
import org.eclipse.basyx.vab.modelprovider.VABPathTools;
import org.eclipse.basyx.vab.modelprovider.api.IModelProvider;
@@ -41,11 +46,12 @@
*
* @param path
* @return
+ * @throws MalformedRequestException if path does not start with PERFIX "api/v1/registry"
*/
- private String stripPrefix(String path) {
+ private String stripPrefix(String path) throws MalformedRequestException {
path = VABPathTools.stripSlashes(path);
if (!path.startsWith(PREFIX)) {
- throw new RuntimeException("Path " + path + " not recognized as registry path. Has to start with " + PREFIX);
+ throw new MalformedRequestException("Path " + path + " not recognized as registry path. Has to start with " + PREFIX);
}
path = path.replace(PREFIX, "");
path = VABPathTools.stripSlashes(path);
@@ -57,8 +63,9 @@
*
* @param path the path to be splitted
* @return Array of path elements
+ * @throws MalformedRequestException if path is not valid
*/
- private String[] splitPath(String path) {
+ private String[] splitPath(String path) throws MalformedRequestException {
if(path.isEmpty()) {
return new String[0];
@@ -68,29 +75,43 @@
//Assumes "submodels" is not a valid AASId
if(splitted[0].equals(SUBMODELS)) {
- throw new RuntimeException("Path must not start with " + SUBMODELS);
+ throw new MalformedRequestException("Path must not start with " + SUBMODELS);
}
//If path contains more than one element, the second one has to be "submodels"
if(splitted.length > 1 && !splitted[1].equals(SUBMODELS)) {
- throw new RuntimeException("Second path element must be (if present): " + SUBMODELS);
+ throw new MalformedRequestException("Second path element must be (if present): " + SUBMODELS);
}
return splitted;
}
+ private String[] preparePath(String path) throws MalformedRequestException {
+ try {
+ path = URLDecoder.decode(path, "UTF-8");
+ } catch (UnsupportedEncodingException e) {
+ //Malformed request because of unsupported encoding
+ throw new MalformedRequestException("Path has to be encoded as UTF-8 string.");
+ }
+
+ path = stripPrefix(path);
+
+ return splitPath(path);
+ }
+
/**
* Checks if a given Object is a Map and checks if it has the correct modelType
*
* @param expectedModelType the modelType the Object is expected to have
* @param value the Object to be checked and casted
* @return the object casted to a Map
+ * @throws MalformedRequestException
*/
@SuppressWarnings("unchecked")
- private Map<String, Object> checkModelType(String expectedModelType, Object value) {
+ private Map<String, Object> checkModelType(String expectedModelType, Object value) throws MalformedRequestException {
//check if the given value is a Map
if(!(value instanceof Map)) {
- throw new RuntimeException("Given newValue is not a Map");
+ throw new MalformedRequestException("Given newValue is not a Map");
}
Map<String, Object> map = (Map<String, Object>) value;
@@ -101,7 +122,7 @@
//have to accept Objects without modeltype information,
//as modeltype is not part of the public metamodel
if(!expectedModelType.equals(type) && type != null) {
- throw new RuntimeException("Given newValue map has not the correct ModelType");
+ throw new MalformedRequestException("Given newValue map has not the correct ModelType");
}
return map;
@@ -113,8 +134,9 @@
*
* @param value the AAS Map object
* @return an AAS
+ * @throws MalformedRequestException
*/
- private AASDescriptor createAASDescriptorFromMap(Object value) {
+ private AASDescriptor createAASDescriptorFromMap(Object value) throws MalformedRequestException {
Map<String, Object> map = checkModelType(AASDescriptor.MODELTYPE, value);
AASDescriptor aasDescriptor = new AASDescriptor(map);
return aasDescriptor;
@@ -126,32 +148,30 @@
*
* @param value the AAS Map object
* @return an AAS
+ * @throws MalformedRequestException
*/
- private SubmodelDescriptor createSMDescriptorFromMap(Object value) {
+ private SubmodelDescriptor createSMDescriptorFromMap(Object value) throws MalformedRequestException {
Map<String, Object> map = checkModelType(SubmodelDescriptor.MODELTYPE, value);
SubmodelDescriptor smDescriptor = new SubmodelDescriptor(map);
return smDescriptor;
}
@Override
- public Object getModelPropertyValue(String path) throws Exception {
- path = stripPrefix(path);
- path = URLDecoder.decode(path, "UTF-8");
+ public Object getModelPropertyValue(String path) throws ProviderException {
+ String[] splitted = preparePath(path);
//Path is empty, request for all AASDescriptors
- if (path.isEmpty()) {
+ if (splitted.length == 0) {
return registry.lookupAll();
} else {
- String[] splitted = splitPath(path);
-
//Given path consists only of an AAS Id
if(splitted.length == 1) {
- AASDescriptor descriptor = registry.lookupAAS(new ModelUrn(path));
+ AASDescriptor descriptor = registry.lookupAAS(new ModelUrn(splitted[0]));
//Throw an Exception if the requested AAS does not exist
if(descriptor == null) {
- throw new RuntimeException("Specified AASid '" + path + "' does not exist.");
+ throw new ResourceNotFoundException("Specified AASid '" + splitted[0] + "' does not exist.");
}
return descriptor;
@@ -165,28 +185,24 @@
} else if(splitted.length == 3) {
SubmodelDescriptor smDescriptor = getSmDescriptorFromAAS(new ModelUrn(splitted[0]), splitted[2]);
if(smDescriptor == null) {
- throw new RuntimeException("Specified SubmodelId '" + splitted[2] + "' does not exist in AAS '" + splitted[0] + "'.");
+ throw new ResourceNotFoundException("Specified SubmodelId '" + splitted[2] + "' does not exist in AAS '" + splitted[0] + "'.");
}
return smDescriptor;
}
//path has more than three elements and is therefore invalid
- throw new RuntimeException("Given path '" + path + "' contains more than three path elements and is therefore invalid.");
+ throw new MalformedRequestException("Given path '" + path + "' contains more than three path elements and is therefore invalid.");
}
}
@Override
- public void setModelPropertyValue(String path, Object newValue) throws Exception {
- path = stripPrefix(path);
- path = URLDecoder.decode(path, "UTF-8");
+ public void setModelPropertyValue(String path, Object newValue) throws ProviderException {
+ String[] splitted = preparePath(path);
- if (!path.isEmpty()) { // Overwriting existing entry
-
- String[] splitted = splitPath(path);
-
+ if (splitted.length > 0) { // Overwriting existing entry
//if path contains more or less than an aasID after the prefix
if(splitted.length != 1) {
- throw new RuntimeException("Path '" + path + "' is invalid for updating an aas.");
+ throw new MalformedRequestException("Path '" + path + "' is invalid for updating an aas.");
}
// Decode encoded path
@@ -194,23 +210,20 @@
//aas to be updated does not exist
if(registry.lookupAAS(identifier) == null) {
- throw new RuntimeException("AAS '" + path + "' to be updated does not exist. Try create instead.");
+ throw new ResourceNotFoundException("AAS '" + path + "' to be updated does not exist. Try create instead.");
}
//delete old value and create the new one
registry.delete(identifier);
registry.register(createAASDescriptorFromMap(newValue));
} else {
- throw new RuntimeException("Set with empty path is not supported by registry");
+ throw new MalformedRequestException("Set with empty path is not supported by registry");
}
}
@Override
- public void createValue(String path, Object newEntity) throws Exception {
- path = stripPrefix(path);
- path = URLDecoder.decode(path, "UTF-8");
-
- String[] splitted = splitPath(path);
+ public void createValue(String path, Object newEntity) throws ProviderException {
+ String[] splitted = preparePath(path);
// Creating new entry
if (splitted.length == 0) {
@@ -219,7 +232,7 @@
//aas to be created already exists
if(registry.lookupAAS(aas.getIdentifier()) != null) {
- throw new RuntimeException("AAS with Id '" +
+ throw new ResourceAlreadyExistsException("AAS with Id '" +
aas.getIdentifier().getId() + "' already exists. Try update instead.");
}
@@ -235,23 +248,20 @@
//a submodel with this Id already exists in given aas
//getSmDescriptorFromAAS also checks if aas exists
if(getSmDescriptorFromAAS(aasId, smDescriptor.getIdShort()) != null) {
- throw new RuntimeException("A Submodel with id '" + smDescriptor.getIdShort() +
+ throw new ResourceAlreadyExistsException("A Submodel with id '" + smDescriptor.getIdShort() +
"' already exists in aas '" + splitted[0] + "'. Try update instead.");
}
registry.register(aasId, smDescriptor);
} else {
- throw new RuntimeException("Create was called with an unsupported path: " + path);
+ throw new MalformedRequestException("Create was called with an unsupported path: " + path);
}
}
@Override
- public void deleteValue(String path) throws Exception {
- path = stripPrefix(path);
- path = URLDecoder.decode(path, "UTF-8");
-
- String[] splitted = splitPath(path);
+ public void deleteValue(String path) throws ProviderException {
+ String[] splitted = preparePath(path);
if (splitted.length == 1) { //delete an aas
@@ -259,7 +269,7 @@
//aas to be deleted does not exist
if(registry.lookupAAS(aasId) == null) {
- throw new RuntimeException("AAS '" + splitted[0] + "' to be deleted does not exist.");
+ throw new ResourceNotFoundException("AAS '" + splitted[0] + "' to be deleted does not exist.");
}
registry.delete(aasId);
@@ -272,25 +282,25 @@
//a submodel with this Id does not exist in given aas
//getSmDescriptorFromAAS also checks if aas exists
if(getSmDescriptorFromAAS(aasId, smId) == null) {
- throw new RuntimeException("A Submodel with id '" + smId +
+ throw new ResourceNotFoundException("A Submodel with id '" + smId +
"' does not exist in aas '" + splitted[0] + "'.");
}
registry.delete(aasId, smId);
} else {
- throw new RuntimeException("Delete with empty path is not supported by registry");
+ throw new MalformedRequestException("Delete with empty path is not supported by registry");
}
}
@Override
public void deleteValue(String path, Object obj) throws Exception {
- throw new RuntimeException("DeleteValue with parameter not supported by registry");
+ throw new MalformedRequestException("DeleteValue with parameter not supported by registry");
}
@Override
public Object invokeOperation(String path, Object... parameter) throws Exception {
- throw new RuntimeException("Invoke not supported by registry");
+ throw new MalformedRequestException("Invoke not supported by registry");
}
/**
@@ -299,11 +309,12 @@
*
* @param id id of the aas
* @return Set of contained SubmodelDescriptor objects
+ * @throws ResourceNotFoundException if the AAS does not exist
*/
- private Set<SubmodelDescriptor> getSmDescriptorsFromAAS(IIdentifier id) {
+ private Set<SubmodelDescriptor> getSmDescriptorsFromAAS(IIdentifier id) throws ResourceNotFoundException {
AASDescriptor aasDescriptor = registry.lookupAAS(id);
if(aasDescriptor == null) {
- throw new RuntimeException("Specified AASid '" + id.getId() + "' does not exist.");
+ throw new ResourceNotFoundException("Specified AASid '" + id.getId() + "' does not exist.");
}
return aasDescriptor.getSubModelDescriptors();
}
@@ -315,11 +326,13 @@
* @param aasId id of the aas
* @param smId id of the submodel
* @return the SubmodelDescriptor with the given id
+ * @throws ResourceNotFoundException if aasId does not exist
*/
- private SubmodelDescriptor getSmDescriptorFromAAS(IIdentifier aasId, String smId) {
+ private SubmodelDescriptor getSmDescriptorFromAAS(IIdentifier aasId, String smId)
+ throws ResourceNotFoundException {
AASDescriptor aasDescriptor = registry.lookupAAS(aasId);
if(aasDescriptor == null) {
- throw new RuntimeException("Specified AASid '" + aasId.getId() + "' does not exist.");
+ throw new ResourceNotFoundException("Specified AASid '" + aasId.getId() + "' does not exist.");
}
return aasDescriptor.getSubmodelDescriptorFromIdShort(smId);
diff --git a/sdks/java/basys.sdk/src/main/java/org/eclipse/basyx/vab/coder/json/provider/JSONProvider.java b/sdks/java/basys.sdk/src/main/java/org/eclipse/basyx/vab/coder/json/provider/JSONProvider.java
index 09cc270..5056bd1 100644
--- a/sdks/java/basys.sdk/src/main/java/org/eclipse/basyx/vab/coder/json/provider/JSONProvider.java
+++ b/sdks/java/basys.sdk/src/main/java/org/eclipse/basyx/vab/coder/json/provider/JSONProvider.java
@@ -11,6 +11,8 @@
import org.eclipse.basyx.vab.coder.json.serialization.GSONToolsFactory;
import org.eclipse.basyx.vab.exception.LostHTTPRequestParameterException;
import org.eclipse.basyx.vab.exception.ServerException;
+import org.eclipse.basyx.vab.exception.provider.MalformedRequestException;
+import org.eclipse.basyx.vab.exception.provider.ProviderException;
import org.eclipse.basyx.vab.modelprovider.api.IModelProvider;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -137,29 +139,26 @@
/**
- * Send JSON encoded response
- */
- private void sendJSONResponse(PrintWriter outputStream, String jsonValue) {
- // Write result to output stream
- outputStream.write(jsonValue);
- outputStream.flush();
- }
-
-
- /**
* Send Error
* @param e
* @param path
* @param resp
*/
- private void sendException(PrintWriter resp, Exception e) {
- logger.error("Exception in sendException", e);
+ private void sendException(PrintWriter resp, Exception e) throws ProviderException {
// Serialize Exception
String jsonString = serialize(e);
- // Send error response
- sendJSONResponse(resp, jsonString);
+ resp.write(jsonString);
+
+ //If the Exception is a ProviderException, just rethrow it
+ if(e instanceof ProviderException) {
+ throw (ProviderException) e;
+ }
+
+ //If the Exception is not a ProviderException encapsulate it in one and log it
+ logger.error("Unknown Exception in JSONProvider", e);
+ throw new ProviderException(e);
}
@@ -170,24 +169,31 @@
* @param serializedJSONValue
* @param outputStream
* @return
+ * @throws MalformedRequestException
* @throws LostHTTPRequestParameterException
* @throws ServerException
*/
- private Object extractParameter(String path, String serializedJSONValue, PrintWriter outputStream) {
+ private Object extractParameter(String path, String serializedJSONValue, PrintWriter outputStream) throws MalformedRequestException {
// Return value
Object result = null;
- // Deserialize json body
- result = serializer.deserialize(serializedJSONValue);
-
+ try {
+ // Deserialize json body
+ result = serializer.deserialize(serializedJSONValue);
+ } catch (Exception e) {
+ //JSON could not be deserialized
+ throw new MalformedRequestException(e);
+ }
+
return result;
}
/**
* Process a BaSys get operation, return JSON serialized result
+ * @throws ProviderException
*/
- public void processBaSysGet(String path, PrintWriter outputStream) {
+ public void processBaSysGet(String path, PrintWriter outputStream) throws ProviderException {
try {
// Get requested value from provider backend
@@ -197,7 +203,7 @@
String jsonString = serialize(true, value, null);
// Send response
- sendJSONResponse(outputStream, jsonString);
+ outputStream.write(jsonString);
} catch (Exception e) {
sendException(outputStream, e);
}
@@ -210,8 +216,9 @@
* @param path
* @param serializedJSONValue
* @param outputStream
+ * @throws ProviderException
*/
- public void processBaSysSet(String path, String serializedJSONValue, PrintWriter outputStream) {
+ public void processBaSysSet(String path, String serializedJSONValue, PrintWriter outputStream) throws ProviderException {
// Try to set value of BaSys VAB element
try {
@@ -226,7 +233,7 @@
String jsonString = serialize(true);
// Send response
- sendJSONResponse(outputStream, jsonString);
+ outputStream.write(jsonString);
} catch (Exception e) {
sendException(outputStream, e);
@@ -236,9 +243,10 @@
/**
* Process a BaSys invoke operation
+ * @throws ProviderException
*/
@SuppressWarnings("unchecked")
- public void processBaSysInvoke(String path, String serializedJSONValue, PrintWriter outputStream) {
+ public void processBaSysInvoke(String path, String serializedJSONValue, PrintWriter outputStream) throws ProviderException {
try {
@@ -271,7 +279,7 @@
String jsonString = serialize(true, result, null);
// Send response
- sendJSONResponse(outputStream, jsonString);
+ outputStream.write(jsonString);
} catch (Exception e) {
sendException(outputStream, e);
@@ -285,8 +293,9 @@
* @param path
* @param serializedJSONValue If this parameter is not null (basystype),we remove an element from a collection by index / remove from map by key. We assume that the parameter only contains 1 element
* @param outputStream
+ * @throws ProviderException
*/
- public void processBaSysDelete(String path, String serializedJSONValue, PrintWriter outputStream) {
+ public void processBaSysDelete(String path, String serializedJSONValue, PrintWriter outputStream) throws ProviderException {
try {
@@ -304,7 +313,7 @@
String jsonString = serialize(true);
// Send response
- sendJSONResponse(outputStream, jsonString);
+ outputStream.write(jsonString);
} catch (Exception e) {
sendException(outputStream, e);
@@ -318,8 +327,9 @@
* @param path
* @param parameter
* @param outputStream
+ * @throws ProviderException
*/
- public void processBaSysCreate(String path, String serializedJSONValue, PrintWriter outputStream) {
+ public void processBaSysCreate(String path, String serializedJSONValue, PrintWriter outputStream) throws ProviderException {
try {
// Deserialize json body.
@@ -332,7 +342,7 @@
String jsonString = serialize(true);
// Send response
- sendJSONResponse(outputStream, jsonString);
+ outputStream.write(jsonString);
} catch (Exception e) {
sendException(outputStream, e);
diff --git a/sdks/java/basys.sdk/src/main/java/org/eclipse/basyx/vab/protocol/basyx/server/VABBaSyxTCPInterface.java b/sdks/java/basys.sdk/src/main/java/org/eclipse/basyx/vab/protocol/basyx/server/VABBaSyxTCPInterface.java
index b13416b..4d1fd95 100644
--- a/sdks/java/basys.sdk/src/main/java/org/eclipse/basyx/vab/protocol/basyx/server/VABBaSyxTCPInterface.java
+++ b/sdks/java/basys.sdk/src/main/java/org/eclipse/basyx/vab/protocol/basyx/server/VABBaSyxTCPInterface.java
@@ -8,6 +8,7 @@
import java.nio.channels.SocketChannel;
import org.eclipse.basyx.vab.coder.json.provider.JSONProvider;
+import org.eclipse.basyx.vab.exception.provider.ProviderException;
import org.eclipse.basyx.vab.modelprovider.api.IModelProvider;
import org.eclipse.basyx.vab.protocol.basyx.CoderTools;
import org.slf4j.Logger;
@@ -92,11 +93,20 @@
String path = new String(rxFrame, 1 + 4, pathLen);
// Forward request to provider
- providerBackend.processBaSysGet(path, output);
+ try {
+ providerBackend.processBaSysGet(path, output);
+ } catch (ProviderException e) {
+ logger.error("Exception in BASYX_GET", e);
+ // Catch Exceptions from JSONProvider
+ // No further action here, as the current version
+ // of the TCP-Mapping states, that always Statuscode 0x00
+ // should be returned with Exceptions encoded in returned String
+ }
// System.out.println("Processed GET:"+path);
// Send response frame
+ output.flush();
sendResponseFrame(byteArrayOutput);
break;
@@ -111,9 +121,18 @@
String jsonValue = new String(rxFrame, 1 + 4 + pathLen + 4, jsonValueLen);
// Invoke get operation
- providerBackend.processBaSysSet(path, jsonValue, output);
+ try {
+ providerBackend.processBaSysSet(path, jsonValue, output);
+ } catch (ProviderException e) {
+ logger.error("Exception in BASYX_SET", e);
+ // Catch Exceptions from JSONProvider
+ // No further action here, as the current version
+ // of the TCP-Mapping states, that always Statuscode 0x00
+ // should be returned with Exceptions encoded in returned String
+ }
// Send response frame
+ output.flush();
sendResponseFrame(byteArrayOutput);
break;
@@ -128,9 +147,18 @@
String jsonValue = new String(rxFrame, 1 + 4 + pathLen + 4, jsonValueLen);
// Invoke get operation
- providerBackend.processBaSysCreate(path, jsonValue, output);
+ try {
+ providerBackend.processBaSysCreate(path, jsonValue, output);
+ } catch (ProviderException e) {
+ logger.error("Exception in BASYX_CREATE", e);
+ // Catch Exceptions from JSONProvider
+ // No further action here, as the current version
+ // of the TCP-Mapping states, that always Statuscode 0x00
+ // should be returned with Exceptions encoded in returned String
+ }
// Send response frame
+ output.flush();
sendResponseFrame(byteArrayOutput);
break;
@@ -154,9 +182,18 @@
}
// Invoke delete operation
- providerBackend.processBaSysDelete(path, jsonValue, output);
+ try {
+ providerBackend.processBaSysDelete(path, jsonValue, output);
+ } catch (ProviderException e) {
+ logger.error("Exception in BASYX_DELETE", e);
+ // Catch Exceptions from JSONProvider
+ // No further action here, as the current version
+ // of the TCP-Mapping states, that always Statuscode 0x00
+ // should be returned with Exceptions encoded in returned String
+ }
// Send response frame
+ output.flush();
sendResponseFrame(byteArrayOutput);
break;
@@ -170,9 +207,18 @@
int jsonValueLen = CoderTools.getInt32(rxFrame, 1 + 4 + pathLen);
String jsonValue = new String(rxFrame, 1 + 4 + pathLen + 4, jsonValueLen);
// Invoke get operation
- providerBackend.processBaSysInvoke(path, jsonValue, output);
+ try {
+ providerBackend.processBaSysInvoke(path, jsonValue, output);
+ } catch (ProviderException e) {
+ logger.error("Exception in BASYX_INVOKE", e);
+ // Catch Exceptions from JSONProvider
+ // No further action here, as the current version
+ // of the TCP-Mapping states, that always Statuscode 0x00
+ // should be returned with Exceptions encoded in returned String
+ }
// Send response frame
+ output.flush();
sendResponseFrame(byteArrayOutput);
break;
diff --git a/sdks/java/basys.sdk/src/main/java/org/eclipse/basyx/vab/protocol/http/server/ExceptionToHTTPCodeMapper.java b/sdks/java/basys.sdk/src/main/java/org/eclipse/basyx/vab/protocol/http/server/ExceptionToHTTPCodeMapper.java
new file mode 100644
index 0000000..454b9dd
--- /dev/null
+++ b/sdks/java/basys.sdk/src/main/java/org/eclipse/basyx/vab/protocol/http/server/ExceptionToHTTPCodeMapper.java
@@ -0,0 +1,36 @@
+package org.eclipse.basyx.vab.protocol.http.server;
+
+import org.eclipse.basyx.vab.exception.provider.MalformedRequestException;
+import org.eclipse.basyx.vab.exception.provider.ProviderException;
+import org.eclipse.basyx.vab.exception.provider.ResourceAlreadyExistsException;
+import org.eclipse.basyx.vab.exception.provider.ResourceNotFoundException;
+
+/**
+ * Maps Exceptions from providers to HTTP-Codes
+ *
+ * @author conradi
+ *
+ */
+public class ExceptionToHTTPCodeMapper {
+
+
+ /**
+ * Maps ProviderExceptions to HTTP-Codes
+ *
+ * @param e The thrown ProviderException
+ * @return HTTP-Code
+ */
+ public static int mapException(ProviderException e) {
+
+ if(e instanceof MalformedRequestException) {
+ return 400;
+ } else if(e instanceof ResourceAlreadyExistsException) {
+ return 422;
+ } else if(e instanceof ResourceNotFoundException) {
+ return 404;
+ }
+ return 500;
+
+ }
+
+}
diff --git a/sdks/java/basys.sdk/src/main/java/org/eclipse/basyx/vab/protocol/http/server/VABHTTPInterface.java b/sdks/java/basys.sdk/src/main/java/org/eclipse/basyx/vab/protocol/http/server/VABHTTPInterface.java
index cdb470e..8d7ba63 100644
--- a/sdks/java/basys.sdk/src/main/java/org/eclipse/basyx/vab/protocol/http/server/VABHTTPInterface.java
+++ b/sdks/java/basys.sdk/src/main/java/org/eclipse/basyx/vab/protocol/http/server/VABHTTPInterface.java
@@ -3,13 +3,13 @@
import java.io.IOException;
import java.io.PrintWriter;
import java.io.UnsupportedEncodingException;
-
import javax.servlet.ServletException;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.eclipse.basyx.vab.coder.json.provider.JSONProvider;
+import org.eclipse.basyx.vab.exception.provider.ProviderException;
import org.eclipse.basyx.vab.modelprovider.VABPathTools;
import org.eclipse.basyx.vab.modelprovider.api.IModelProvider;
@@ -91,9 +91,22 @@
// Setup HTML response header
resp.setContentType("application/json");
resp.setCharacterEncoding("UTF-8");
-
- // Process get request
- providerBackend.processBaSysGet(path, resp.getWriter());
+
+ resp.setStatus(200);
+
+ PrintWriter responseWriter = resp.getWriter();
+
+ try {
+ // Process get request
+ providerBackend.processBaSysGet(path, responseWriter);
+ responseWriter.flush();
+ } catch(ProviderException e) {
+ int httpCode = ExceptionToHTTPCodeMapper.mapException(e);
+ resp.setStatus(httpCode);
+ responseWriter.flush();
+ logger.error("Exception in HTTP-GET. Response-code: " + httpCode, e);
+ }
+
}
@@ -106,7 +119,19 @@
String serValue = extractSerializedValue(req);
logger.trace("DoPut: {}", serValue);
- providerBackend.processBaSysSet(path, serValue.toString(), resp.getWriter());
+ resp.setStatus(200);
+
+ PrintWriter responseWriter = resp.getWriter();
+
+ try {
+ providerBackend.processBaSysSet(path, serValue.toString(), responseWriter);
+ responseWriter.flush();
+ } catch(ProviderException e) {
+ int httpCode = ExceptionToHTTPCodeMapper.mapException(e);
+ resp.setStatus(httpCode);
+ responseWriter.flush();
+ logger.error("Exception in HTTP-PUT. Response-code: " + httpCode, e);
+ }
}
@@ -123,16 +148,35 @@
logger.trace("DoPost: {}", serValue);
// Setup HTML response header
+ resp.setStatus(201);
resp.setContentType("application/json");
resp.setCharacterEncoding("UTF-8");
+
+ PrintWriter responseWriter = resp.getWriter();
// Check if request is for property creation or operation invoke
if (VABPathTools.isOperationPath(path)) {
// Invoke BaSys VAB 'invoke' primitive
- providerBackend.processBaSysInvoke(path, serValue, resp.getWriter());
+ try {
+ providerBackend.processBaSysInvoke(path, serValue, responseWriter);
+ responseWriter.flush();
+ } catch(ProviderException e) {
+ int httpCode = ExceptionToHTTPCodeMapper.mapException(e);
+ resp.setStatus(httpCode);
+ responseWriter.flush();
+ logger.error("Exception in HTTP-POST. Response-code: " + httpCode, e);
+ }
} else {
// Invoke the BaSys 'create' primitive
- providerBackend.processBaSysCreate(path, serValue, resp.getWriter());
+ try {
+ providerBackend.processBaSysCreate(path, serValue, responseWriter);
+ responseWriter.flush();
+ } catch(ProviderException e) {
+ int httpCode = ExceptionToHTTPCodeMapper.mapException(e);
+ resp.setStatus(httpCode);
+ responseWriter.flush();
+ logger.error("Exception in HTTP-POST. Response-code: " + httpCode, e);
+ }
}
}
@@ -147,7 +191,19 @@
String serValue = extractSerializedValue(req);
logger.trace("DoPatch: {}", serValue);
- providerBackend.processBaSysDelete(path, serValue, resp.getWriter());
+ resp.setStatus(200);
+
+ PrintWriter responseWriter = resp.getWriter();
+
+ try {
+ providerBackend.processBaSysDelete(path, serValue, responseWriter);
+ responseWriter.flush();
+ } catch(ProviderException e) {
+ int httpCode = ExceptionToHTTPCodeMapper.mapException(e);
+ resp.setStatus(httpCode);
+ responseWriter.flush();
+ logger.error("Exception in HTTP-PATCH. Response-code: " + httpCode, e);
+ }
}
@@ -161,7 +217,19 @@
// No parameter to read! Provide serialized null
String nullParam = "";
- providerBackend.processBaSysDelete(path, nullParam, resp.getWriter());
+ resp.setStatus(200);
+
+ PrintWriter responseWriter = resp.getWriter();
+
+ try {
+ providerBackend.processBaSysDelete(path, nullParam, responseWriter);
+ responseWriter.flush();
+ } catch(ProviderException e) {
+ int httpCode = ExceptionToHTTPCodeMapper.mapException(e);
+ resp.setStatus(httpCode);
+ responseWriter.flush();
+ logger.error("Exception in HTTP-DELETE. Response-code: " + httpCode, e);
+ }
}
diff --git a/sdks/java/basys.sdk/src/test/java/org/eclipse/basyx/testsuite/regression/vab/coder/json/IBasyxConnectorFacade.java b/sdks/java/basys.sdk/src/test/java/org/eclipse/basyx/testsuite/regression/vab/coder/json/IBasyxConnectorFacade.java
index 4183b75..50ffb75 100644
--- a/sdks/java/basys.sdk/src/test/java/org/eclipse/basyx/testsuite/regression/vab/coder/json/IBasyxConnectorFacade.java
+++ b/sdks/java/basys.sdk/src/test/java/org/eclipse/basyx/testsuite/regression/vab/coder/json/IBasyxConnectorFacade.java
@@ -3,6 +3,7 @@
import java.io.FileNotFoundException;
import org.eclipse.basyx.vab.coder.json.provider.JSONProvider;
+import org.eclipse.basyx.vab.exception.provider.ProviderException;
import org.eclipse.basyx.vab.modelprovider.api.IModelProvider;
import org.eclipse.basyx.vab.protocol.api.IBaSyxConnector;
import org.slf4j.Logger;
@@ -39,7 +40,7 @@
provider.processBaSysGet(path, outputstream);
return outputstream.getResult();
- } catch (FileNotFoundException e) {
+ } catch (FileNotFoundException | ProviderException e) {
logger.error("[TEST] Exception in getModelPropertyValue", e);
}
return null;