/** * Resolve the class name from the given {@code serializedType}. This method may be overridden to customize * the names used to denote certain classes, for example, by leaving out a certain base package for brevity. * * @param serializedType The serialized type to resolve the class name for * @return The fully qualified name of the class to load */ protected String resolveClassName(SerializedType serializedType) { return serializedType.getName(); }
@Override public Class classForType(SerializedType type) { if (SerializedType.emptyType().equals(type)) { return Void.class; } try { return Class.forName(type.getName()); } catch (ClassNotFoundException e) { return UnknownSerializedType.class; } }
private String getSagaTypeName(Class<?> sagaType) { return serializer.typeForClass(sagaType).getName(); }
private String sagaTypeName(Class<?> sagaType) { return serializer.typeForClass(sagaType).getName(); }
/** * Indicates whether the given {@code serializedObject} represents a serialized form of a MetaData object, * such as the ones created by this class (see {@link #SerializedMetaData(Object, Class)}. * * @param serializedObject The object to check for Meta Data * @return {@code true} if the serialized objects represents serialized meta data, otherwise * {@code false}. */ public static boolean isSerializedMetaData(SerializedObject<?> serializedObject) { return serializedObject != null && serializedObject.getType() != null && METADATA_CLASS_NAME.equals(serializedObject.getType().getName()); }
private static void putDeadlineScope(JobDataMap jobData, ScopeDescriptor deadlineScope, Serializer serializer) { SerializedObject<byte[]> serializedDeadlineScope = serializer.serialize(deadlineScope, byte[].class); jobData.put(SERIALIZED_DEADLINE_SCOPE, serializedDeadlineScope.getData()); jobData.put(SERIALIZED_DEADLINE_SCOPE_CLASS_NAME, serializedDeadlineScope.getType().getName()); }
@Override public Class classForType(SerializedType type) { if (SerializedType.emptyType().equals(type)) { return Void.class; } try { return xStream.getMapper().realClass(type.getName()); } catch (CannotResolveClassException e) { return UnknownSerializedType.class; } }
@Override public <S> Entry<S> loadSaga(Class<S> sagaType, String sagaIdentifier) { EntityManager entityManager = entityManagerProvider.getEntityManager(); final Class<? extends SimpleSerializedObject<?>> serializedObjectType = serializedObjectType(); List<? extends SimpleSerializedObject<?>> serializedSagaList = entityManager.createNamedQuery(LOAD_SAGA_NAMED_QUERY, serializedObjectType) .setParameter("sagaId", sagaIdentifier) .setMaxResults(1) .getResultList(); if (serializedSagaList == null || serializedSagaList.isEmpty()) { return null; } final SimpleSerializedObject<?> serializedSaga = serializedSagaList.get(0); S loadedSaga = serializer.deserialize(serializedSaga); Set<AssociationValue> associationValues = loadAssociationValues(entityManager, sagaType, sagaIdentifier); if (logger.isDebugEnabled()) { logger.debug("Loaded saga id [{}] of type [{}]", sagaIdentifier, serializedSaga.getType().getName()); } return new EntryImpl<>(associationValues, loadedSaga); }
private static void putDeadlineMessage(JobDataMap jobData, DeadlineMessage deadlineMessage, Serializer serializer) { jobData.put(DEADLINE_NAME, deadlineMessage.getDeadlineName()); jobData.put(MESSAGE_ID, deadlineMessage.getIdentifier()); jobData.put(MESSAGE_TIMESTAMP, deadlineMessage.getTimestamp().toEpochMilli()); SerializedObject<byte[]> serializedDeadlinePayload = serializer.serialize(deadlineMessage.getPayload(), byte[].class); jobData.put(SERIALIZED_MESSAGE_PAYLOAD, serializedDeadlinePayload.getData()); jobData.put(MESSAGE_TYPE, serializedDeadlinePayload.getType().getName()); jobData.put(MESSAGE_REVISION, serializedDeadlinePayload.getType().getRevision()); SerializedObject<byte[]> serializedDeadlineMetaData = serializer.serialize(deadlineMessage.getMetaData(), byte[].class); jobData.put(MESSAGE_METADATA, serializedDeadlineMetaData.getData()); }
@Override public JobDataMap toJobData(Object event) { JobDataMap jobData = new JobDataMap(); EventMessage eventMessage = (EventMessage) event; jobData.put(MESSAGE_ID, eventMessage.getIdentifier()); jobData.put(MESSAGE_TIMESTAMP, eventMessage.getTimestamp().toEpochMilli()); SerializedObject<byte[]> serializedPayload = serializer.serialize(eventMessage.getPayload(), byte[].class); jobData.put(SERIALIZED_MESSAGE_PAYLOAD, serializedPayload.getData()); jobData.put(MESSAGE_TYPE, serializedPayload.getType().getName()); jobData.put(MESSAGE_REVISION, serializedPayload.getType().getRevision()); SerializedObject<byte[]> serializedMetaData = serializer.serialize(eventMessage.getMetaData(), byte[].class); jobData.put(MESSAGE_METADATA, serializedMetaData.getData()); return jobData; }
/** * Update the token data to the given {@code token}, using given {@code serializer} to serialize it to the given * {@code contentType}. * * @param token The token representing the state to update to * @param serializer The serializer to update token to * @param contentType The type of data to represent the serialized data in */ protected final void updateToken(TrackingToken token, Serializer serializer, Class<T> contentType) { SerializedObject<T> serializedToken = serializer.serialize(token, contentType); this.token = serializedToken.getData(); this.tokenType = serializedToken.getType().getName(); this.timestamp = formatInstant(clock.instant()); } }
/** * Initializes a new token entry for given {@code token}, {@code process} and {@code segment}. The given {@code * serializer} can be used to serialize the token before it is stored. * * @param token The tracking token to store * @param serializer The serializer to use when storing a serialized token * @param contentType The content type after serialization */ protected AbstractTokenEntry(TrackingToken token, Serializer serializer, Class<T> contentType) { this.timestamp = formatInstant(clock.instant()); if (token != null) { SerializedObject<T> serializedToken = serializer.serialize(token, contentType); this.token = serializedToken.getData(); this.tokenType = serializedToken.getType().getName(); } }
/** * Constructs a new SagaEntry for the given {@code saga}. The given saga must be serializable. The provided * saga is not modified by this operation. * * @param saga The saga to store * @param sagaIdentifier The saga identifier * @param serializer The serialization mechanism to convert the Saga to a byte stream * @param contentType The saga content type to serialize to */ public AbstractSagaEntry(Object saga, String sagaIdentifier, Serializer serializer, Class<T> contentType) { this.sagaId = sagaIdentifier; SerializedObject<T> serialized = serializer.serialize(saga, contentType); this.serializedSaga = serialized.getData(); this.sagaType = serialized.getType().getName(); this.revision = serialized.getType().getRevision(); }
@Override public io.axoniq.axonserver.grpc.SerializedObject apply(O o) { SerializedObject<byte[]> serializedPayload = serializer.serialize(o, byte[].class); return io.axoniq.axonserver.grpc.SerializedObject.newBuilder() .setData(ByteString.copyFrom(serializedPayload.getData())) .setType(serializedPayload.getType().getName()) .setRevision(getOrDefault(serializedPayload.getType().getRevision(), "")) .build(); } }
/** * Initializes a ReplyMessage containing a reply to the command with given {commandIdentifier} and given * {@code commandResultMessage}. * * @param commandIdentifier the identifier of the command to which the message is a reply * @param commandResultMessage the result message of command process * @param serializer the serializer to serialize the message contents with */ public ReplyMessage(String commandIdentifier, CommandResultMessage<?> commandResultMessage, Serializer serializer) { this.commandIdentifier = commandIdentifier; SerializedObject<byte[]> metaData = commandResultMessage.serializeMetaData(serializer, byte[].class); this.serializedMetaData = metaData.getData(); SerializedObject<byte[]> payload = commandResultMessage.serializePayload(serializer, byte[].class); this.serializedPayload = payload.getData(); this.payloadType = payload.getType().getName(); this.payloadRevision = payload.getType().getRevision(); SerializedObject<byte[]> exception = commandResultMessage.serializeExceptionResult(serializer, byte[].class); this.serializedException = exception.getData(); this.exceptionType = exception.getType().getName(); this.exceptionRevision = exception.getType().getRevision(); }
/** * Initialized a DispatchMessage for the given {@code commandMessage}, which uses the given * {@code serializer} to deserialize its contents. * {@code expectReply} indicates whether the sender will be expecting a reply. * * @param commandMessage The message to send to the remote segment * @param serializer The serialize to serialize the message payload and metadata with * @param expectReply whether or not the sender is waiting for a reply. */ protected DispatchMessage(CommandMessage<?> commandMessage, Serializer serializer, boolean expectReply) { this.commandIdentifier = commandMessage.getIdentifier(); SerializedObject<byte[]> metaData = commandMessage.serializeMetaData(serializer, byte[].class); this.serializedMetaData = metaData.getData(); SerializedObject<byte[]> payload = commandMessage.serializePayload(serializer, byte[].class); this.payloadType = payload.getType().getName(); this.payloadRevision = payload.getType().getRevision(); this.serializedPayload = payload.getData(); this.commandName = commandMessage.getCommandName(); this.expectReply = expectReply; }
/** * Construct a new event entry from a published event message to enable storing the event or sending it to a remote * location. * <p> * The given {@code serializer} will be used to serialize the payload and metadata in the given {@code eventMessage}. * The type of the serialized data will be the same as the given {@code contentType}. * * @param eventMessage The event message to convert to a serialized event entry * @param serializer The serializer to convert the event * @param contentType The data type of the payload and metadata after serialization */ public AbstractEventEntry(EventMessage<?> eventMessage, Serializer serializer, Class<T> contentType) { SerializedObject<T> payload = eventMessage.serializePayload(serializer, contentType); SerializedObject<T> metaData = eventMessage.serializeMetaData(serializer, contentType); this.eventIdentifier = eventMessage.getIdentifier(); this.payloadType = payload.getType().getName(); this.payloadRevision = payload.getType().getRevision(); this.payload = payload.getData(); this.metaData = metaData.getData(); this.timeStamp = formatInstant(eventMessage.getTimestamp()); }
/** * If the given {@code resultSet} has no items this method should insert a new token entry. If a token already * exists it should be attempted to replace the token in the entry with the given {@code token} and claim ownership. * * @param resultSet the updatable query result set of an executed {@link PreparedStatement} * @param token the token for the new or updated entry * @param processorName the name of the processor owning the token * @param segment the segment of the processor owning the token * @throws UnableToClaimTokenException if the token cannot be claimed because another node currently owns the token * @throws SQLException when an exception occurs while updating the result set */ protected void insertOrUpdateToken(ResultSet resultSet, TrackingToken token, String processorName, int segment) throws SQLException { if (resultSet.next()) { AbstractTokenEntry<?> entry = readTokenEntry(resultSet); entry.updateToken(token, serializer); resultSet.updateObject(schema.tokenColumn(), entry.getSerializedToken().getData()); resultSet.updateString(schema.tokenTypeColumn(), entry.getSerializedToken().getType().getName()); resultSet.updateString(schema.timestampColumn(), entry.timestampAsString()); claimToken(resultSet, entry); } else { insertTokenEntry(resultSet, token, processorName, segment); } }
public Event map(EventMessage<?> eventMessage, Serializer serializer) { Event.Builder builder = Event.newBuilder(); if (eventMessage instanceof GenericDomainEventMessage) { builder.setAggregateIdentifier(((GenericDomainEventMessage) eventMessage).getAggregateIdentifier()) .setAggregateSequenceNumber(((GenericDomainEventMessage) eventMessage).getSequenceNumber()) .setAggregateType(((GenericDomainEventMessage) eventMessage).getType()); } SerializedObject<byte[]> serializedPayload = eventMessage.serializePayload(serializer, byte[].class); builder.setMessageIdentifier(eventMessage.getIdentifier()).setPayload( io.axoniq.axonserver.grpc.SerializedObject.newBuilder() .setType(serializedPayload.getType().getName()) .setRevision(getOrDefault( serializedPayload.getType().getRevision(), "" )) .setData(ByteString.copyFrom(serializedPayload.getData())) ).setTimestamp(eventMessage.getTimestamp().toEpochMilli()); eventMessage.getMetaData().forEach((k, v) -> builder.putMetaData(k, converter.convertToMetaDataValue(v))); return builder.build(); }
/** * Inserts a new token entry via the given updatable {@code resultSet}. * * @param resultSet the updatable result set to add the entry to * @param token the token of the entry to insert * @param processorName the name of the processor to insert a token for * @param segment the segment of the processor to insert a token for * @return the tracking token of the inserted entry * * @throws SQLException when an exception occurs while inserting a token entry */ protected TrackingToken insertTokenEntry(ResultSet resultSet, TrackingToken token, String processorName, int segment) throws SQLException { AbstractTokenEntry<?> entry = new GenericTokenEntry<>(token, serializer, contentType, processorName, segment); entry.claim(nodeId, claimTimeout); resultSet.moveToInsertRow(); resultSet.updateObject(schema.tokenColumn(), token == null ? null : entry.getSerializedToken().getData()); resultSet.updateString(schema.tokenTypeColumn(), token == null ? null : entry.getSerializedToken().getType().getName()); resultSet.updateString(schema.timestampColumn(), entry.timestampAsString()); resultSet.updateString(schema.ownerColum(), entry.getOwner()); resultSet.updateString(schema.processorNameColumn(), processorName); resultSet.updateInt(schema.segmentColumn(), segment); resultSet.insertRow(); return token; }