diff --git a/commons-rest/errors/pom.xml b/commons-rest/errors/pom.xml index 910d050272e..508547af40f 100644 --- a/commons-rest/errors/pom.xml +++ b/commons-rest/errors/pom.xml @@ -31,6 +31,10 @@ org.eclipse.kapua kapua-endpoint-api + + org.eclipse.kapua + kapua-service-storable-api + diff --git a/commons-rest/errors/src/main/java/org/eclipse/kapua/commons/rest/errors/StorableNotFoundExceptionMapper.java b/commons-rest/errors/src/main/java/org/eclipse/kapua/commons/rest/errors/StorableNotFoundExceptionMapper.java new file mode 100644 index 00000000000..febe55d65d4 --- /dev/null +++ b/commons-rest/errors/src/main/java/org/eclipse/kapua/commons/rest/errors/StorableNotFoundExceptionMapper.java @@ -0,0 +1,46 @@ +/******************************************************************************* + * Copyright (c) 2017, 2022 Eurotech and/or its affiliates and others + * + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Eurotech - initial API and implementation + *******************************************************************************/ +package org.eclipse.kapua.commons.rest.errors; + +import org.eclipse.kapua.commons.rest.model.errors.StorableNotFoundExceptionInfo; +import org.eclipse.kapua.service.storable.exception.StorableNotFoundException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.inject.Inject; +import javax.ws.rs.core.Response; +import javax.ws.rs.core.Response.Status; +import javax.ws.rs.ext.ExceptionMapper; +import javax.ws.rs.ext.Provider; + +@Provider +public class StorableNotFoundExceptionMapper implements ExceptionMapper { + + private static final Logger LOG = LoggerFactory.getLogger(StorableNotFoundExceptionMapper.class); + + private final boolean showStackTrace; + + @Inject + public StorableNotFoundExceptionMapper(ExceptionConfigurationProvider exceptionConfigurationProvider) { + this.showStackTrace = exceptionConfigurationProvider.showStackTrace(); + } + + @Override + public Response toResponse(StorableNotFoundException kapuaEntityNotFoundException) { + LOG.error(kapuaEntityNotFoundException.getMessage(), kapuaEntityNotFoundException); + return Response + .status(Status.NOT_FOUND) + .entity(new StorableNotFoundExceptionInfo(Status.NOT_FOUND.getStatusCode(), kapuaEntityNotFoundException, showStackTrace)) + .build(); + } +} diff --git a/commons-rest/model/pom.xml b/commons-rest/model/pom.xml index 64f4cfbf14a..d7f55401ef2 100644 --- a/commons-rest/model/pom.xml +++ b/commons-rest/model/pom.xml @@ -42,6 +42,10 @@ org.eclipse.kapua kapua-scheduler-api + + org.eclipse.kapua + kapua-service-storable-api + diff --git a/commons-rest/model/src/main/java/org/eclipse/kapua/commons/rest/model/errors/StorableNotFoundExceptionInfo.java b/commons-rest/model/src/main/java/org/eclipse/kapua/commons/rest/model/errors/StorableNotFoundExceptionInfo.java new file mode 100644 index 00000000000..08e06a39f7c --- /dev/null +++ b/commons-rest/model/src/main/java/org/eclipse/kapua/commons/rest/model/errors/StorableNotFoundExceptionInfo.java @@ -0,0 +1,78 @@ +/******************************************************************************* + * Copyright (c) 2024, 2022 Eurotech and/or its affiliates and others + * + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Eurotech - initial API and implementation + *******************************************************************************/ +package org.eclipse.kapua.commons.rest.model.errors; + +import org.eclipse.kapua.model.id.KapuaIdAdapter; +import org.eclipse.kapua.service.storable.exception.StorableNotFoundException; +import org.eclipse.kapua.service.storable.model.id.StorableId; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlRootElement; +import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter; + +@XmlRootElement(name = "storableNotFoundExceptionInfo") +@XmlAccessorType(XmlAccessType.FIELD) +public class StorableNotFoundExceptionInfo extends ExceptionInfo { + + @XmlElement(name = "storableType") + private String storableType; + + @XmlElement(name = "storableId") + @XmlJavaTypeAdapter(KapuaIdAdapter.class) + private StorableId storableId; + + /** + * Constructor. + * + * @since 2.0.0 + */ + protected StorableNotFoundExceptionInfo() { + super(); + } + + /** + * Constructor. + * + * @param httpStatusCode The http status code of the response containing this info + * @param storableNotFoundException The {@link StorableNotFoundException}. + * @since 2.0.0 + */ + public StorableNotFoundExceptionInfo(int httpStatusCode, StorableNotFoundException storableNotFoundException, boolean showStackTrace) { + super(httpStatusCode, storableNotFoundException, showStackTrace); + + this.storableType = storableNotFoundException.getStorableType(); + this.storableId = storableNotFoundException.getStorableId(); + } + + /** + * Gets the {@link StorableNotFoundException#getStorableType()} + * + * @return The {@link StorableNotFoundException#getStorableType()}. + * @since 2.0.0 + */ + public String getEntityType() { + return storableType; + } + + /** + * Gets the {@link StorableNotFoundException#getStorableId()}. + * + * @return The {@link StorableNotFoundException#getStorableId()}. + * @since 2.0.0 + */ + public StorableId getStorableId() { + return storableId; + } +} diff --git a/rest-api/core/src/main/java/org/eclipse/kapua/app/api/core/model/data/JsonDatastoreMessage.java b/rest-api/core/src/main/java/org/eclipse/kapua/app/api/core/model/data/JsonDatastoreMessage.java index 3cac692563a..fb95b818f38 100644 --- a/rest-api/core/src/main/java/org/eclipse/kapua/app/api/core/model/data/JsonDatastoreMessage.java +++ b/rest-api/core/src/main/java/org/eclipse/kapua/app/api/core/model/data/JsonDatastoreMessage.java @@ -56,6 +56,11 @@ public JsonDatastoreMessage(DatastoreMessage datastoreMessage) { setPayload(datastoreMessage.getPayload()); } + @Override + public String getType() { + return DatastoreMessage.TYPE; + } + @XmlElement(name = "datastoreId") @XmlJavaTypeAdapter(StorableIdXmlAdapter.class) public StorableId getDatastoreId() { diff --git a/rest-api/core/src/main/java/org/eclipse/kapua/app/api/core/resources/AbstractKapuaResource.java b/rest-api/core/src/main/java/org/eclipse/kapua/app/api/core/resources/AbstractKapuaResource.java index 67a852ce6d3..fbe6dc46aed 100644 --- a/rest-api/core/src/main/java/org/eclipse/kapua/app/api/core/resources/AbstractKapuaResource.java +++ b/rest-api/core/src/main/java/org/eclipse/kapua/app/api/core/resources/AbstractKapuaResource.java @@ -15,6 +15,9 @@ import org.eclipse.kapua.KapuaEntityNotFoundException; import org.eclipse.kapua.model.KapuaEntity; import org.eclipse.kapua.model.id.KapuaId; +import org.eclipse.kapua.service.storable.exception.StorableNotFoundException; +import org.eclipse.kapua.service.storable.model.Storable; +import org.eclipse.kapua.service.storable.model.id.StorableId; import javax.ws.rs.NotFoundException; import javax.ws.rs.WebApplicationException; @@ -68,6 +71,27 @@ public T returnNotNullEntity(T entity, String entityType return entity; } + /** + * Checks id the given {@link Storable} is {@code null}. + *

+ * Similar to {@link #returnNotNullEntity(KapuaEntity, String, KapuaId)} but for {@link Storable}s. + * + * @param storable The {@link Storable} to check. + * @param storableType The {@link Storable#getType()} + * @param storableId The {@link StorableId} + * @return The given {@link Storable} if not {@code null} + * @param The type of the {@link Storable}. + * @throws StorableNotFoundException if given {@link Storable} is {@code null}. + * @since 2.0.0 + */ + public T returnNotNullStorable(T storable, String storableType, StorableId storableId) throws StorableNotFoundException { + if (storable == null) { + throw new StorableNotFoundException(storableType, storableId); + } + + return storable; + } + /** * Builds a 200 HTTP Response. * diff --git a/rest-api/resources/src/main/java/org/eclipse/kapua/app/api/resources/v1/resources/DataChannels.java b/rest-api/resources/src/main/java/org/eclipse/kapua/app/api/resources/v1/resources/DataChannels.java index dcd7bd12cba..6150b2c7ef8 100644 --- a/rest-api/resources/src/main/java/org/eclipse/kapua/app/api/resources/v1/resources/DataChannels.java +++ b/rest-api/resources/src/main/java/org/eclipse/kapua/app/api/resources/v1/resources/DataChannels.java @@ -191,6 +191,6 @@ public ChannelInfo find(@PathParam("scopeId") ScopeId scopeId, throws KapuaException { ChannelInfo channelInfo = channelInfoRegistryService.find(scopeId, channelInfoId); - return returnNotNullEntity(channelInfo); + return returnNotNullStorable(channelInfo, ChannelInfo.TYPE, channelInfoId); } } diff --git a/rest-api/resources/src/main/java/org/eclipse/kapua/app/api/resources/v1/resources/DataClients.java b/rest-api/resources/src/main/java/org/eclipse/kapua/app/api/resources/v1/resources/DataClients.java index 04cc47abf10..64c63cd1974 100644 --- a/rest-api/resources/src/main/java/org/eclipse/kapua/app/api/resources/v1/resources/DataClients.java +++ b/rest-api/resources/src/main/java/org/eclipse/kapua/app/api/resources/v1/resources/DataClients.java @@ -170,6 +170,6 @@ public ClientInfo find(@PathParam("scopeId") ScopeId scopeId, throws KapuaException { ClientInfo clientInfo = clientInfoRegistryService.find(scopeId, clientInfoId); - return returnNotNullEntity(clientInfo); + return returnNotNullStorable(clientInfo, ClientInfo.TYPE, clientInfoId); } } diff --git a/rest-api/resources/src/main/java/org/eclipse/kapua/app/api/resources/v1/resources/DataMessages.java b/rest-api/resources/src/main/java/org/eclipse/kapua/app/api/resources/v1/resources/DataMessages.java index 99ca6fb94b2..0627364438d 100644 --- a/rest-api/resources/src/main/java/org/eclipse/kapua/app/api/resources/v1/resources/DataMessages.java +++ b/rest-api/resources/src/main/java/org/eclipse/kapua/app/api/resources/v1/resources/DataMessages.java @@ -204,7 +204,7 @@ public DatastoreMessage find(@PathParam("scopeId") ScopeId scopeId, throws KapuaException { DatastoreMessage datastoreMessage = messageStoreService.find(scopeId, datastoreMessageId, StorableFetchStyle.SOURCE_FULL); - return returnNotNullEntity(datastoreMessage); + return returnNotNullStorable(datastoreMessage, DatastoreMessage.TYPE, datastoreMessageId); } //TODO: move this logic within the service, or at least in a collaborator shared with DataMessagesJson diff --git a/rest-api/resources/src/main/java/org/eclipse/kapua/app/api/resources/v1/resources/DataMessagesJson.java b/rest-api/resources/src/main/java/org/eclipse/kapua/app/api/resources/v1/resources/DataMessagesJson.java index e27df7455d7..a0308b9aa6c 100644 --- a/rest-api/resources/src/main/java/org/eclipse/kapua/app/api/resources/v1/resources/DataMessagesJson.java +++ b/rest-api/resources/src/main/java/org/eclipse/kapua/app/api/resources/v1/resources/DataMessagesJson.java @@ -221,11 +221,11 @@ public JsonMessageListResult queryJson(@PathParam("scopeId") ScopeId scopeId, public JsonDatastoreMessage findJson(@PathParam("scopeId") ScopeId scopeId, @PathParam("datastoreMessageId") StorableEntityId datastoreMessageId) throws KapuaException { - DatastoreMessage datastoreMessage = returnNotNullEntity(messageStoreService.find(scopeId, datastoreMessageId, StorableFetchStyle.SOURCE_FULL)); + DatastoreMessage datastoreMessage = returnNotNullStorable(messageStoreService.find(scopeId, datastoreMessageId, StorableFetchStyle.SOURCE_FULL), DatastoreMessage.TYPE, datastoreMessageId); JsonDatastoreMessage jsonDatastoreMessage = new JsonDatastoreMessage(datastoreMessage); - return returnNotNullEntity(jsonDatastoreMessage); + return returnNotNullStorable(jsonDatastoreMessage, DatastoreMessage.TYPE, datastoreMessageId); } private MessageQuery convertQuery(JsonMessageQuery query) { diff --git a/rest-api/resources/src/main/java/org/eclipse/kapua/app/api/resources/v1/resources/DataMetrics.java b/rest-api/resources/src/main/java/org/eclipse/kapua/app/api/resources/v1/resources/DataMetrics.java index 650b0245928..c17e92c0465 100644 --- a/rest-api/resources/src/main/java/org/eclipse/kapua/app/api/resources/v1/resources/DataMetrics.java +++ b/rest-api/resources/src/main/java/org/eclipse/kapua/app/api/resources/v1/resources/DataMetrics.java @@ -177,6 +177,6 @@ public MetricInfo find(@PathParam("scopeId") ScopeId scopeId, throws KapuaException { MetricInfo metricInfo = metricInfoRegistryService.find(scopeId, metricInfoId); - return returnNotNullEntity(metricInfo); + return returnNotNullStorable(metricInfo, MetricInfo.TYPE, metricInfoId); } } diff --git a/rest-api/web/src/main/java/org/eclipse/kapua/app/api/web/RestApiJAXBContextProvider.java b/rest-api/web/src/main/java/org/eclipse/kapua/app/api/web/RestApiJAXBContextProvider.java index 2bcc3851d41..6f66b5e040d 100644 --- a/rest-api/web/src/main/java/org/eclipse/kapua/app/api/web/RestApiJAXBContextProvider.java +++ b/rest-api/web/src/main/java/org/eclipse/kapua/app/api/web/RestApiJAXBContextProvider.java @@ -59,6 +59,7 @@ import org.eclipse.kapua.commons.rest.model.errors.SelfManagedOnlyExceptionInfo; import org.eclipse.kapua.commons.rest.model.errors.ServiceConfigurationLimitExceededExceptionInfo; import org.eclipse.kapua.commons.rest.model.errors.ServiceConfigurationParentLimitExceededExceptionInfo; +import org.eclipse.kapua.commons.rest.model.errors.StorableNotFoundExceptionInfo; import org.eclipse.kapua.commons.rest.model.errors.SubjectUnauthorizedExceptionInfo; import org.eclipse.kapua.commons.rest.model.errors.ThrowableInfo; import org.eclipse.kapua.commons.service.event.store.api.EventStoreRecordCreator; @@ -366,6 +367,7 @@ public JAXBContext getJAXBContext() throws KapuaException { IllegalArgumentExceptionInfo.class, IllegalNullArgumentExceptionInfo.class, MfaRequiredExceptionInfo.class, + StorableNotFoundExceptionInfo.class, // Jobs Exception Info CleanJobDataExceptionInfo.class, diff --git a/service/commons/storable/api/src/main/java/org/eclipse/kapua/service/storable/exception/StorableErrorCodes.java b/service/commons/storable/api/src/main/java/org/eclipse/kapua/service/storable/exception/StorableErrorCodes.java index 4e1b7cfbcf1..0109b160d9b 100644 --- a/service/commons/storable/api/src/main/java/org/eclipse/kapua/service/storable/exception/StorableErrorCodes.java +++ b/service/commons/storable/api/src/main/java/org/eclipse/kapua/service/storable/exception/StorableErrorCodes.java @@ -33,5 +33,12 @@ public enum StorableErrorCodes implements KapuaErrorCode { * * @since 1.3.0 */ - UNSUPPORTED_TYPE + UNSUPPORTED_TYPE, + + /** + * See {@link StorableNotFoundException} + * + * @since 2.0.0 + */ + STORABLE_NOT_FOUND } diff --git a/service/commons/storable/api/src/main/java/org/eclipse/kapua/service/storable/exception/StorableNotFoundException.java b/service/commons/storable/api/src/main/java/org/eclipse/kapua/service/storable/exception/StorableNotFoundException.java new file mode 100644 index 00000000000..f681c454f1d --- /dev/null +++ b/service/commons/storable/api/src/main/java/org/eclipse/kapua/service/storable/exception/StorableNotFoundException.java @@ -0,0 +1,62 @@ +/******************************************************************************* + * Copyright (c) 2024, 2022 Eurotech and/or its affiliates and others + * + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Eurotech - initial API and implementation + *******************************************************************************/ +package org.eclipse.kapua.service.storable.exception; + +import org.eclipse.kapua.KapuaException; +import org.eclipse.kapua.service.storable.model.Storable; +import org.eclipse.kapua.service.storable.model.id.StorableId; + +/** + * {@link StorableNotFoundException} is thrown when an {@link Storable} could not be loaded from the database. + * + * @since 2.0.0 + */ +public class StorableNotFoundException extends KapuaException { + + private final String storableType; + private final StorableId storableId; + + /** + * Constructor. + * + * @param storableType The {@link Storable#getType()}. + * @param storableId The {@link StorableId}. + * @since 2.0.0 + */ + public StorableNotFoundException(String storableType, StorableId storableId) { + super(StorableErrorCodes.STORABLE_NOT_FOUND, storableType, storableId); + + this.storableType = storableType; + this.storableId = storableId; + } + + /** + * Gets the {@link Storable#getType()}. + * + * @return The {@link Storable#getType()}. + * @since 2.0.0 + */ + public String getStorableType() { + return storableType; + } + + /** + * Gets the {@link StorableId}. + * + * @return The {@link StorableId}. + * @since 2.0.0 + */ + public StorableId getStorableId() { + return storableId; + } +} diff --git a/service/commons/storable/api/src/main/java/org/eclipse/kapua/service/storable/model/Storable.java b/service/commons/storable/api/src/main/java/org/eclipse/kapua/service/storable/model/Storable.java index 7616ec38b48..b6e98890e4d 100644 --- a/service/commons/storable/api/src/main/java/org/eclipse/kapua/service/storable/model/Storable.java +++ b/service/commons/storable/api/src/main/java/org/eclipse/kapua/service/storable/model/Storable.java @@ -17,6 +17,7 @@ import org.eclipse.kapua.model.id.KapuaIdAdapter; import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlTransient; import javax.xml.bind.annotation.XmlType; import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter; @@ -30,6 +31,15 @@ @XmlType(propOrder = {"scopeId"}) public interface Storable extends KapuaSerializable { + /** + * Gets the type. + * + * @return The type. + * @since 2.0.0 + */ + @XmlTransient + String getType(); + /** * Gets the scope {@link KapuaId}. * diff --git a/service/commons/storable/api/src/main/resources/storable-error-messages.properties b/service/commons/storable/api/src/main/resources/storable-error-messages.properties index d2f4520fb02..ee286c6e5bf 100644 --- a/service/commons/storable/api/src/main/resources/storable-error-messages.properties +++ b/service/commons/storable/api/src/main/resources/storable-error-messages.properties @@ -12,3 +12,4 @@ ############################################################################### UNSUPPORTED_TYPE=The conversion of mapping {0} of value {1} of type {2} with is not supported! INVALID_VALUE=The value of mapping {0} of value {1} is not compatible with type {2}. +STORABLE_NOT_FOUND=The storable of type {0} with id {1} was not found. diff --git a/service/datastore/api/src/main/java/org/eclipse/kapua/service/datastore/model/ChannelInfo.java b/service/datastore/api/src/main/java/org/eclipse/kapua/service/datastore/model/ChannelInfo.java index 43ce5623614..cf301b301e2 100644 --- a/service/datastore/api/src/main/java/org/eclipse/kapua/service/datastore/model/ChannelInfo.java +++ b/service/datastore/api/src/main/java/org/eclipse/kapua/service/datastore/model/ChannelInfo.java @@ -43,6 +43,13 @@ }) public interface ChannelInfo extends Storable { + String TYPE = "ChannelInfo"; + + @Override + default String getType() { + return TYPE; + } + /** * Gets the {@link StorableId} * diff --git a/service/datastore/api/src/main/java/org/eclipse/kapua/service/datastore/model/ClientInfo.java b/service/datastore/api/src/main/java/org/eclipse/kapua/service/datastore/model/ClientInfo.java index d040177fa0d..46c51455cb5 100644 --- a/service/datastore/api/src/main/java/org/eclipse/kapua/service/datastore/model/ClientInfo.java +++ b/service/datastore/api/src/main/java/org/eclipse/kapua/service/datastore/model/ClientInfo.java @@ -42,6 +42,13 @@ }) public interface ClientInfo extends Storable { + String TYPE = "ClientInfo"; + + @Override + default String getType() { + return TYPE; + } + /** * Gets the {@link StorableId} * diff --git a/service/datastore/api/src/main/java/org/eclipse/kapua/service/datastore/model/DatastoreMessage.java b/service/datastore/api/src/main/java/org/eclipse/kapua/service/datastore/model/DatastoreMessage.java index cc41e7762f0..bcdafd69ef3 100644 --- a/service/datastore/api/src/main/java/org/eclipse/kapua/service/datastore/model/DatastoreMessage.java +++ b/service/datastore/api/src/main/java/org/eclipse/kapua/service/datastore/model/DatastoreMessage.java @@ -53,6 +53,14 @@ }) public interface DatastoreMessage extends Storable { + String TYPE = "DatastoreMessage"; + + @Override + default String getType() { + return TYPE; + } + + /** * Get the message identifier * diff --git a/service/datastore/api/src/main/java/org/eclipse/kapua/service/datastore/model/MetricInfo.java b/service/datastore/api/src/main/java/org/eclipse/kapua/service/datastore/model/MetricInfo.java index 3f69eb2ba93..f6110b92b8d 100644 --- a/service/datastore/api/src/main/java/org/eclipse/kapua/service/datastore/model/MetricInfo.java +++ b/service/datastore/api/src/main/java/org/eclipse/kapua/service/datastore/model/MetricInfo.java @@ -45,6 +45,12 @@ "lastMessageOn"}) public interface MetricInfo extends Storable { + String TYPE = "MetricInfo"; + + @Override + default String getType() { + return TYPE; + } /** * Gets the {@link StorableId}