Skip to content

Commit

Permalink
Improved exception handling for REST API; #72; #80
Browse files Browse the repository at this point in the history
  • Loading branch information
phax committed Nov 3, 2018
1 parent b181e6a commit 7467340
Show file tree
Hide file tree
Showing 41 changed files with 1,583 additions and 1,444 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ public final class SMPServerConfiguration
public static final String KEY_SMP_IDENTIFIER_TYPE = "smp.identifiertype";
public static final String KEY_SMP_REST_TYPE = "smp.rest.type";
public static final String KEY_SMP_REST_WRITABLE_API_DISABLED = "smp.rest.writableapi.disabled";
public static final String KEY_SMP_REST_LOG_EXCEPTIONS = "smp.rest.log.exceptions";
public static final String KEY_SMP_STATUS_ENABLED = "smp.status.enabled";
public static final String KEY_SMP_PEPPOL_DIRECTORY_INTEGRATION_ENABLED = "smp.peppol.directory.integration.enabled";
public static final String KEY_SMP_PEPPOL_DIRECTORY_INTEGRATION_AUTO_UPDATE = "smp.peppol.directory.integration.autoupdate";
Expand All @@ -85,6 +86,7 @@ public final class SMPServerConfiguration
public static final ESMPIdentifierType DEFAULT_SMP_IDENTIFIER_TYPE = ESMPIdentifierType.PEPPOL;
public static final ESMPRESTType DEFAULT_SMP_REST_TYPE = ESMPRESTType.PEPPOL;
public static final boolean DEFAULT_SMP_REST_WRITABLE_API_DISABLED = false;
public static final boolean DEFAULT_SMP_REST_LOG_EXCEPTIONS = false;
public static final boolean DEFAULT_SMP_STATUS_ENABLED = true;
public static final boolean DEFAULT_SMP_PEPPOL_DIRECTORY_INTEGRATION_ENABLED = true;
public static final boolean DEFAULT_SMP_PEPPOL_DIRECTORY_INTEGRATION_AUTO_UPDATE = true;
Expand Down Expand Up @@ -300,6 +302,16 @@ public static ESMPRESTType getRESTType ()
return ESMPRESTType.getFromIDOrDefault (sType, DEFAULT_SMP_REST_TYPE);
}

/**
* @return <code>true</code> if the exceptions in the REST API should be
* logged, <code>false</code> if not. By default it is disabled.
* @since 5.1.0
*/
public static boolean isRESTLogExceptions ()
{
return getConfigFile ().getAsBoolean (KEY_SMP_REST_LOG_EXCEPTIONS, DEFAULT_SMP_REST_LOG_EXCEPTIONS);
}

/**
* @return <code>true</code> if the status servlet at
* <code>/smp-status/</code> is enabled, <code>false</code> if it is
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
import com.helger.peppol.identifier.factory.IIdentifierFactory;
import com.helger.peppol.identifier.factory.PeppolIdentifierFactory;
import com.helger.peppol.identifier.factory.SimpleIdentifierFactory;
import com.helger.peppol.identifier.generic.participant.IParticipantIdentifier;
import com.helger.peppol.smpserver.ESMPIdentifierType;
import com.helger.peppol.smpserver.SMPServerConfiguration;
import com.helger.peppol.smpserver.backend.SMPBackendRegistry;
Expand All @@ -32,6 +33,7 @@
import com.helger.peppol.smpserver.domain.servicegroup.ISMPServiceGroupCallback;
import com.helger.peppol.smpserver.domain.servicegroup.ISMPServiceGroupManager;
import com.helger.peppol.smpserver.domain.servicegroup.LoggingSMPServiceGroupCallback;
import com.helger.peppol.smpserver.domain.servicegroup.SMPServiceGroup;
import com.helger.peppol.smpserver.domain.serviceinfo.ISMPServiceInformationManager;
import com.helger.peppol.smpserver.domain.sml.ISMLInfoManager;
import com.helger.peppol.smpserver.domain.transportprofile.ISMPTransportProfileManager;
Expand Down Expand Up @@ -120,8 +122,9 @@ private void _initCallbacks ()
m_aServiceGroupMgr.serviceGroupCallbacks ().add (new ISMPServiceGroupCallback ()
{
@Override
public void onSMPServiceGroupDeleted (@Nonnull final String sServiceGroupID)
public void onSMPServiceGroupDeleted (@Nonnull final IParticipantIdentifier aParticipantID)
{
final String sServiceGroupID = SMPServiceGroup.createSMPServiceGroupID (aParticipantID);
final ISMPBusinessCard aBusinessCard = m_aBusinessCardMgr.getSMPBusinessCardOfID (sServiceGroupID);
if (aBusinessCard != null)
m_aBusinessCardMgr.deleteSMPBusinessCard (aBusinessCard);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
import javax.annotation.Nonnull;

import com.helger.commons.callback.ICallback;
import com.helger.peppol.identifier.generic.participant.IParticipantIdentifier;

/**
* Interface for an SMP service group callback.
Expand All @@ -33,18 +34,18 @@ default void onSMPServiceGroupCreated (@Nonnull final ISMPServiceGroup aServiceG
/**
* Invoked after an SMP service group was updated.
*
* @param sServiceGroupID
* The updated object. Never <code>null</code>.
* @param aParticipantID
* The ID of the updated object. Never <code>null</code>.
*/
default void onSMPServiceGroupUpdated (@Nonnull final String sServiceGroupID)
default void onSMPServiceGroupUpdated (@Nonnull final IParticipantIdentifier aParticipantID)
{}

/**
* Invoked after an SMP service group was deleted.
*
* @param sServiceGroupID
* The deleted object. Never <code>null</code>.
* @param aParticipantID
* The ID of the deleted object. Never <code>null</code>.
*/
default void onSMPServiceGroupDeleted (@Nonnull final String sServiceGroupID)
default void onSMPServiceGroupDeleted (@Nonnull final IParticipantIdentifier aParticipantID)
{}
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
import com.helger.peppol.identifier.generic.participant.IParticipantIdentifier;
import com.helger.peppol.smpserver.domain.redirect.ISMPRedirectManager;
import com.helger.peppol.smpserver.domain.serviceinfo.ISMPServiceInformationManager;
import com.helger.peppol.smpserver.exception.SMPServerException;

/**
* Base interface for a manager for {@link ISMPServiceGroup} objects.
Expand Down Expand Up @@ -50,36 +51,54 @@ public interface ISMPServiceGroupManager extends ISMPServiceGroupProvider
* @param sExtension
* The optional extension element that must be either a well-formed XML
* string (for PEPPOL SMP) or a valid JSON string (for BDXR SMP).
* @return The created service group object. May be <code>null</code> to
* indicate the persistent storage failed.
* @return The created service group object. Never <code>null</code>.
* @throws SMPServerException
* In case of error
* @see com.helger.peppol.smp.SMPExtensionConverter
* @see com.helger.peppol.bdxr.BDXRExtensionConverter
*/
@Nullable
@Nonnull
ISMPServiceGroup createSMPServiceGroup (@Nonnull @Nonempty String sOwnerID,
@Nonnull IParticipantIdentifier aParticipantIdentifier,
@Nullable String sExtension);
@Nullable String sExtension) throws SMPServerException;

/**
* Update an existing service group. Note: the participant ID of a service
* group cannot be changed.
*
* @param sSMPServiceGroupID
* The ID of the service group to modify. Maybe <code>null</code>.
* @param aParticipantIdentifier
* The ID of the service group to modify. May not be <code>null</code>.
* @param sOwnerID
* The ID of the (new) owning user. May neither be <code>null</code>
* nor empty.
* @param sExtension
* The optional (new) extension element that must be well-formed XML if
* present.
* @throws SMPServerException
* In case of error
* @return {@link EChange#CHANGED} if the passed service group is contained
* and at least one field was changed, {@link EChange#UNCHANGED}
* otherwise.
*/
@Nonnull
EChange updateSMPServiceGroup (@Nullable String sSMPServiceGroupID,
EChange updateSMPServiceGroup (@Nonnull IParticipantIdentifier aParticipantIdentifier,
@Nonnull @Nonempty String sOwnerID,
@Nullable String sExtension);
@Nullable String sExtension) throws SMPServerException;

@Nonnull
default EChange updateSMPServiceGroupNoEx (@Nonnull final IParticipantIdentifier aParticipantIdentifier,
@Nonnull @Nonempty final String sOwnerID,
@Nullable final String sExtension)
{
try
{
return updateSMPServiceGroup (aParticipantIdentifier, sOwnerID, sExtension);
}
catch (final SMPServerException ex)
{
return EChange.UNCHANGED;
}
}

/**
* Delete an existing service group. If the service group exists and can be
Expand All @@ -89,14 +108,30 @@ EChange updateSMPServiceGroup (@Nullable String sSMPServiceGroupID,
* in the SML!
*
* @param aParticipantIdentifier
* The participant identifier to be deleted. May be <code>null</code>.
* The participant identifier to be deleted. May not be
* <code>null</code>.
* @return {@link EChange#CHANGED} if the passed service group is contained
* and was successfully deleted, {@link EChange#UNCHANGED} otherwise.
* @throws SMPServerException
* In case of error
* @see ISMPServiceInformationManager#deleteAllSMPServiceInformationOfServiceGroup(ISMPServiceGroup)
* @see ISMPRedirectManager#deleteAllSMPRedirectsOfServiceGroup(ISMPServiceGroup)
*/
@Nonnull
EChange deleteSMPServiceGroup (@Nullable IParticipantIdentifier aParticipantIdentifier);
EChange deleteSMPServiceGroup (@Nonnull IParticipantIdentifier aParticipantIdentifier) throws SMPServerException;

@Nonnull
default EChange deleteSMPServiceGroupNoEx (@Nonnull final IParticipantIdentifier aParticipantIdentifier)
{
try
{
return deleteSMPServiceGroup (aParticipantIdentifier);
}
catch (final SMPServerException ex)
{
return EChange.UNCHANGED;
}
}

/**
* @return A non-<code>null</code> but maybe empty list of all contained
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,7 @@
import com.helger.commons.state.ESuccess;
import com.helger.http.basicauth.BasicAuthClientCredentials;
import com.helger.peppol.identifier.generic.participant.IParticipantIdentifier;
import com.helger.peppol.smpserver.exception.SMPNotFoundException;
import com.helger.peppol.smpserver.exception.SMPUnauthorizedException;
import com.helger.peppol.smpserver.exception.SMPServerException;

/**
* Abstraction interface for the user management depending on the used backend.
Expand Down Expand Up @@ -64,13 +63,13 @@ public interface ISMPUserManager extends ISMPUserProvider
* @param aCredentials
* The credentials to be validated. May not be <code>null</code>.
* @return The matching non-<code>null</code> {@link ISMPUser}.
* @throws Exception
* @throws SMPServerException
* If no user matching the passed user name is present or if the
* password in the credentials does not match the stored password
* (hash).
*/
@Nonnull
ISMPUser validateUserCredentials (@Nonnull BasicAuthClientCredentials aCredentials) throws Exception;
ISMPUser validateUserCredentials (@Nonnull BasicAuthClientCredentials aCredentials) throws SMPServerException;

/**
* Verify that the passed service group is owned by the user specified in the
Expand All @@ -81,12 +80,13 @@ public interface ISMPUserManager extends ISMPUserProvider
* @param aCurrentUser
* The user to verify.
* @return Implementation specific return value.
* @throws SMPNotFoundException
* If the passed service group does not exist on this SMP.
* @throws SMPUnauthorizedException
* If the participant identifier is not owned by the user specified in
* the credentials
* @throws SMPServerException
* <code>SMPNotFoundException</code> If the passed service group does
* not exist on this SMP. <code>SMPUnauthorizedException</code> If the
* participant identifier is not owned by the user specified in the
* credentials
*/
@Nullable
Object verifyOwnership (@Nonnull final IParticipantIdentifier aServiceGroupID, @Nonnull final ISMPUser aCurrentUser);
Object verifyOwnership (@Nonnull final IParticipantIdentifier aServiceGroupID,
@Nonnull final ISMPUser aCurrentUser) throws SMPServerException;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
/**
* Copyright (C) 2015-2018 Philip Helger and contributors
* philip[at]helger[dot]com
*
* The Original Code is Copyright The PEPPOL project (http://www.peppol.eu)
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
package com.helger.peppol.smpserver.exception;

import java.net.URI;

import javax.annotation.Nonnull;
import javax.annotation.Nullable;

/**
* HTTP 400 (Bad Request) exception wrapper
*
* @author Philip Helger
* @since 5.1.0
*/
public class SMPBadRequestException extends SMPServerException
{
/**
* Create a HTTP 400 (Bad request) exception.
*
* @param sMessage
* the String that is the entity of the HTTP response.
* @param aNotFoundURI
* The URI that was not found.
*/
public SMPBadRequestException (@Nonnull final String sMessage, @Nullable final URI aNotFoundURI)
{
super ("Bad request: " + sMessage + (aNotFoundURI == null ? "" : " at " + aNotFoundURI));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package com.helger.peppol.smpserver.exception;

import javax.annotation.Nonnull;

/**
* Exception that is thrown to indicate an HTTP 500 error.
*
* @author Philip Helger
* @since 5.1.0
*/
public class SMPInternalErrorException extends SMPServerException
{
public SMPInternalErrorException (@Nonnull final String sMsg, @Nonnull final Throwable aCause)
{
super (sMsg, aCause);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,11 @@
import javax.annotation.Nonnull;
import javax.annotation.Nullable;

/**
* HTTP 404 exception wrapper
*
* @author Philip Helger
*/
public class SMPNotFoundException extends SMPServerException
{
/**
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
/**
* Copyright (C) 2015-2018 Philip Helger and contributors
* philip[at]helger[dot]com
*
* The Original Code is Copyright The PEPPOL project (http://www.peppol.eu)
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
package com.helger.peppol.smpserver.exception;

import javax.annotation.Nonnull;

import com.helger.peppol.smpserver.smlhook.RegistrationHookException;

/**
* This exception is thrown if an error occurred communicating with the SML
*
* @author Philip Helger
* @since 5.1.0
*/
public class SMPSMLException extends SMPServerException
{
public SMPSMLException (@Nonnull final String sMsg, @Nonnull final RegistrationHookException aCause)
{
super (sMsg, aCause);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,18 @@

/**
* Base class for all SMP server specific exceptions
*
*
* @author Philip Helger
*/
public class SMPServerException extends RuntimeException
public class SMPServerException extends Exception
{
public SMPServerException (@Nonnull final String sMessage)
{
super (sMessage);
}

public SMPServerException (@Nonnull final String sMessage, @Nonnull final Throwable aCause)
{
super (sMessage, aCause);
}
}
Loading

0 comments on commit 7467340

Please sign in to comment.