Fix AmqpMessageDispatcherServiceTest.testSendCancelRequest - set action tenant (#2098)

Signed-off-by: Avgustin Marinov <Avgustin.Marinov@bosch.com>
This commit is contained in:
Avgustin Marinov
2024-11-22 17:36:07 +02:00
committed by GitHub
parent 9df68e2d97
commit 4de34eacc3
12 changed files with 42 additions and 61 deletions

View File

@@ -72,8 +72,7 @@ public class EventPublisherAutoConfiguration {
} }
/** /**
* @return default {@link ApplicationEventFilter} that does not filter any * @return default {@link ApplicationEventFilter} that does not filter any events
* events
*/ */
@Bean @Bean
@ConditionalOnMissingBean @ConditionalOnMissingBean

View File

@@ -66,7 +66,7 @@ public class BaseAmqpService {
return ObjectUtils.isEmpty(message.getBody()); return ObjectUtils.isEmpty(message.getBody());
} }
protected static final void logAndThrowMessageError(final Message message, final String error) { protected static void logAndThrowMessageError(final Message message, final String error) {
log.debug("Warning! \"{}\" reported by message: {}", error, message); log.debug("Warning! \"{}\" reported by message: {}", error, message);
throw new AmqpRejectAndDontRequeueException(error); throw new AmqpRejectAndDontRequeueException(error);
} }

View File

@@ -90,4 +90,4 @@ public class DelayedRequeueExceptionStrategy extends ConditionalRejectingErrorHa
cause instanceof MessageConversionException || cause instanceof MessageConversionException ||
cause instanceof MessageHandlingException; cause instanceof MessageHandlingException;
} }
} }

View File

@@ -27,8 +27,7 @@ public class MessageConversionExceptionHandler extends AbstractAmqpErrorHandler<
@Override @Override
public String getErrorMessage(Throwable throwable) { public String getErrorMessage(Throwable throwable) {
final String errorMessage = super.getErrorMessage(throwable); final String errorMessage = super.getErrorMessage(throwable);
//since the detailed error message lies in the first parent of current throwable we retrieve it // since the detailed error message lies in the first parent of current throwable we retrieve it and append it to the errorMessage
// and append it to the errorMessage
final Optional<String> detailedErrorMessage = getFirstAncestralErrorMessage(throwable.getCause()); final Optional<String> detailedErrorMessage = getFirstAncestralErrorMessage(throwable.getCause());
return detailedErrorMessage.isPresent() ? (detailedErrorMessage.get() + errorMessage) : errorMessage; return detailedErrorMessage.isPresent() ? (detailedErrorMessage.get() + errorMessage) : errorMessage;
} }

View File

@@ -224,6 +224,7 @@ class AmqpMessageDispatcherServiceTest extends AbstractIntegrationTest {
void testSendCancelRequest() { void testSendCancelRequest() {
final Action action = mock(Action.class); final Action action = mock(Action.class);
when(action.getId()).thenReturn(1L); when(action.getId()).thenReturn(1L);
when(action.getTenant()).thenReturn(TENANT);
when(action.getTarget()).thenReturn(testTarget); when(action.getTarget()).thenReturn(testTarget);
final CancelTargetAssignmentEvent cancelTargetAssignmentDistributionSetEvent = new CancelTargetAssignmentEvent( final CancelTargetAssignmentEvent cancelTargetAssignmentDistributionSetEvent = new CancelTargetAssignmentEvent(
action, serviceMatcher.getBusId()); action, serviceMatcher.getBusId());

View File

@@ -31,6 +31,5 @@ public class CancelTargetAssignmentEvent extends AbstractAssignmentEvent {
public CancelTargetAssignmentEvent(final String tenant, final List<Action> a, final String applicationId) { public CancelTargetAssignmentEvent(final String tenant, final List<Action> a, final String applicationId) {
super(applicationId, tenant, a, applicationId); super(applicationId, tenant, a, applicationId);
} }
} }

View File

@@ -57,8 +57,7 @@ public class RemoteEntityEvent<E extends TenantAwareBaseEntity> extends RemoteId
private E reloadEntityFromRepository() { private E reloadEntityFromRepository() {
try { try {
final Class<E> clazz = (Class<E>) Class.forName(getEntityClass()); final Class<E> clazz = (Class<E>) Class.forName(getEntityClass());
return EventEntityManagerHolder.getInstance().getEventEntityManager().findEntity( return EventEntityManagerHolder.getInstance().getEventEntityManager().findEntity(getTenant(), getEntityId(), clazz);
getTenant(), getEntityId(), clazz);
} catch (final ClassNotFoundException e) { } catch (final ClassNotFoundException e) {
log.error("Cannot reload entity because class is not found", e); log.error("Cannot reload entity because class is not found", e);
} }

View File

@@ -22,24 +22,19 @@ import org.springframework.messaging.converter.MessageConversionException;
import org.springframework.util.MimeType; import org.springframework.util.MimeType;
/** /**
* A customize message converter for the spring cloud events. The converter is * A customize message converter for the spring cloud events. The converter is registered for the application/binary+protostuff type.
* registered for the application/binary+protostuff type. * <p/>
* * The clazz-type-information is encoded into the message payload infront with a length of {@link #EVENT_TYPE_LENGTH}. This is necessary
* The clazz-type-information is encoded into the message payload infront with a * due in case of rabbitMQ batching the message headers will be merged together and custom message header information will get lost.
* length of {@link #EVENT_TYPE_LENGTH}. This is necessary due in case of * So in this implementation the information about the event-type is encoded in the payload of the message directly using the encoded
* rabbitMQ batching the message headers will be merged together and custom * values of {@link EventType}.
* message header information will get lost. So in this implementation the
* information about the event-type is encoded in the payload of the message
* directly using the encoded values of {@link EventType}.
*/ */
@Slf4j @Slf4j
public class BusProtoStuffMessageConverter extends AbstractMessageConverter { public class BusProtoStuffMessageConverter extends AbstractMessageConverter {
public static final MimeType APPLICATION_BINARY_PROTOSTUFF = new MimeType("application", "binary+protostuff"); public static final MimeType APPLICATION_BINARY_PROTOSTUFF = new MimeType("application", "binary+protostuff");
/** /** The length of the class type length of the payload. */
* The length of the class type length of the payload.
*/
private static final byte EVENT_TYPE_LENGTH = 2; private static final byte EVENT_TYPE_LENGTH = 2;
public BusProtoStuffMessageConverter() { public BusProtoStuffMessageConverter() {
@@ -52,8 +47,7 @@ public class BusProtoStuffMessageConverter extends AbstractMessageConverter {
} }
@Override @Override
public Object convertFromInternal(final Message<?> message, final Class<?> targetClass, public Object convertFromInternal(final Message<?> message, final Class<?> targetClass, final Object conversionHint) {
final Object conversionHint) {
final Object objectPayload = message.getPayload(); final Object objectPayload = message.getPayload();
if (objectPayload instanceof byte[] payload) { if (objectPayload instanceof byte[] payload) {
final byte[] clazzHeader = extractClazzHeader(payload); final byte[] clazzHeader = extractClazzHeader(payload);
@@ -66,13 +60,9 @@ public class BusProtoStuffMessageConverter extends AbstractMessageConverter {
} }
@Override @Override
protected Object convertToInternal(final Object payload, final MessageHeaders headers, protected Object convertToInternal(final Object payload, final MessageHeaders headers, final Object conversionHint) {
final Object conversionHint) {
final byte[] clazzHeader = writeClassHeader(payload.getClass()); final byte[] clazzHeader = writeClassHeader(payload.getClass());
final byte[] writeContent = writeContent(payload); final byte[] writeContent = writeContent(payload);
return mergeClassHeaderAndContent(clazzHeader, writeContent); return mergeClassHeaderAndContent(clazzHeader, writeContent);
} }
@@ -132,4 +122,4 @@ public class BusProtoStuffMessageConverter extends AbstractMessageConverter {
final LinkedBuffer buffer = LinkedBuffer.allocate(); final LinkedBuffer buffer = LinkedBuffer.allocate();
return ProtobufIOUtil.toByteArray(clazzEventType, schema, buffer); return ProtobufIOUtil.toByteArray(clazzEventType, schema, buffer);
} }
} }

View File

@@ -86,10 +86,8 @@ public class EventType {
private int value; private int value;
/** // The associated event-type-value must remain the same as initially
* The associated event-type-value must remain the same as initially // declared. Otherwise, messages cannot correctly de-serialized.
* declared. Otherwise, messages cannot correctly de-serialized.
*/
static { static {
// target // target
TYPES.put(1, TargetCreatedEvent.class); TYPES.put(1, TargetCreatedEvent.class);
@@ -190,10 +188,12 @@ public class EventType {
* does not have a {@link EventType}. * does not have a {@link EventType}.
*/ */
public static EventType from(final Class<?> clazz) { public static EventType from(final Class<?> clazz) {
final Optional<Integer> foundEventType = TYPES.entrySet().stream() return TYPES.entrySet().stream()
.filter(entry -> entry.getValue().equals(clazz)).map(Entry::getKey).findAny(); .filter(entry -> entry.getValue().equals(clazz))
.map(Entry::getKey)
return foundEventType.map(EventType::new).orElse(null); .findAny()
.map(EventType::new)
.orElse(null);
} }
public Class<?> getTargetClass() { public Class<?> getTargetClass() {

View File

@@ -17,8 +17,7 @@ import org.eclipse.hawkbit.tenancy.TenantAware;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
/** /**
* A TenantAwareEvent entity manager, which loads an entity by id and type for * A TenantAwareEvent entity manager, which loads an entity by id and type for remote events.
* remote events.
*/ */
@Transactional(readOnly = true) @Transactional(readOnly = true)
public class JpaEventEntityManager implements EventEntityManager { public class JpaEventEntityManager implements EventEntityManager {
@@ -38,8 +37,7 @@ public class JpaEventEntityManager implements EventEntityManager {
} }
@Override @Override
public <E extends TenantAwareBaseEntity> E findEntity(final String tenant, final Long id, public <E extends TenantAwareBaseEntity> E findEntity(final String tenant, final Long id, final Class<E> entityType) {
final Class<E> entityType) {
return tenantAware.runAsTenant(tenant, () -> entityManager.find(entityType, id)); return tenantAware.runAsTenant(tenant, () -> entityManager.find(entityType, id));
} }
} }

View File

@@ -165,9 +165,8 @@ public class SecurityContextTenantAware implements ContextAware {
} }
/** /**
* An {@link Authentication} implementation to delegate to an existing * An {@link Authentication} implementation to delegate to an existing {@link Authentication} object except setting the details
* {@link Authentication} object except setting the details specifically for * specifically for a specific tenant and user.
* a specific tenant and user.
*/ */
private static final class AuthenticationDelegate implements Authentication { private static final class AuthenticationDelegate implements Authentication {

View File

@@ -65,14 +65,14 @@ public class SystemSecurityContext {
/** /**
* Runs a given {@link Callable} within a system security context, which is * Runs a given {@link Callable} within a system security context, which is
* permitted to call secured system code. Often the system needs to call * permitted to call secured system code. Often the system needs to call
* secured methods by it's own without relying on the current security * secured methods by its own without relying on the current security
* context e.g. if the current security context does not contain the * context e.g. if the current security context does not contain the
* necessary permission it's necessary to execute code as system code to * necessary permission it's necessary to execute code as system code to
* execute necessary methods and functionality. * execute necessary methods and functionality.
* * <br/>
* The security context will be switched to the system code and back after * The security context will be switched to the system code and back after
* the callable is called. * the callable is called.
* * <br/>
* The system code is executed for a current tenant by using the * The system code is executed for a current tenant by using the
* {@link TenantAware#getCurrentTenant()}. * {@link TenantAware#getCurrentTenant()}.
* *
@@ -88,7 +88,7 @@ public class SystemSecurityContext {
/** /**
* Runs a given {@link Callable} within a system security context, which is * Runs a given {@link Callable} within a system security context, which is
* permitted to call secured system code. Often the system needs to call * permitted to call secured system code. Often the system needs to call
* secured methods by it's own without relying on the current security * secured methods by its own without relying on the current security
* context e.g. if the current security context does not contain the * context e.g. if the current security context does not contain the
* necessary permission it's necessary to execute code as system code to * necessary permission it's necessary to execute code as system code to
* execute necessary methods and functionality. * execute necessary methods and functionality.
@@ -120,12 +120,10 @@ public class SystemSecurityContext {
} }
/** /**
* Runs a given {@link Callable} within a system security context, which has * Runs a given {@link Callable} within a system security context, which has the provided {@link GrantedAuthority}s to successfully
* the provided {@link GrantedAuthority}s to successfully run the * run the {@link Callable}.
* {@link Callable}. * <br/>
* * The security context will be switched to a new {@link SecurityContext} and back after the callable is called.
* The security context will be switched to the a new
* {@link SecurityContext} and back after the callable is called.
* *
* @param tenant under which the {@link Callable#call()} must be executed. * @param tenant under which the {@link Callable#call()} must be executed.
* @param callable to call within the security context * @param callable to call within the security context
@@ -193,18 +191,17 @@ public class SystemSecurityContext {
} }
/** /**
* An implementation of the Spring's {@link Authentication} object which is * An implementation of the Spring's {@link Authentication} object which is used within a system security code block and
* used within a system security code block and wraps the original * wraps the original authentication object. The wrapped object contains the necessary {@link SpringEvalExpressions#SYSTEM_ROLE}
* authentication object. The wrapped object contains the necessary * which is allowed to execute all secured methods.
* {@link SpringEvalExpressions#SYSTEM_ROLE} which is allowed to execute all
* secured methods.
*/ */
public static final class SystemCodeAuthentication implements Authentication { public static final class SystemCodeAuthentication implements Authentication {
@Serial @Serial
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
private static final List<SimpleGrantedAuthority> AUTHORITIES = Collections
.singletonList(new SimpleGrantedAuthority(SpringEvalExpressions.SYSTEM_ROLE)); private static final List<SimpleGrantedAuthority> AUTHORITIES =
Collections.singletonList(new SimpleGrantedAuthority(SpringEvalExpressions.SYSTEM_ROLE));
private final Authentication oldAuthentication; private final Authentication oldAuthentication;
private SystemCodeAuthentication(final Authentication oldAuthentication) { private SystemCodeAuthentication(final Authentication oldAuthentication) {