-
Notifications
You must be signed in to change notification settings - Fork 4
Getting started
Idriss Neumann edited this page Oct 15, 2017
·
91 revisions
<repository>
<id>vo-lifecycle-mvn-repo</id>
<url>https://raw.github.com/vo-lifecycle/vo-lifecycle-core/mvn-repo/</url>
<snapshots>
<enabled>true</enabled>
<updatePolicy>always</updatePolicy>
</snapshots>
</repository><dependency>
<groupId>vo-lifecycle</groupId>
<artifactId>vo-lifecycle-core</artifactId>
<version>${vo-lifecycle.version}</version>
</dependency>-
org.volifecycle.lifecyclecomponents:-
LifeCycleSimpleActionImpl: this class implementsLifeCycleActionand is an abstract class which can be extended in order to write a validation state change condition or other workflow's step; -
LifeCycleTransitionImpl: this class implementsLifeCycleTransitionand is a bean which represents a transition (change of one state to another) with a target state and a collection ofLifeCycleAction; -
LifeCycleCompositeActionImpl: this class implementsLifeCycleActionand is provided to represents one of output states when a transition allows multiple output states. This class contains a set ofLifeCycleSimpleActionImpl. -
LifeCycleStateImpl: this class implementsLifeCycleStateand is a bean which represents a value object state and which can be instantiated with a collection ofLifeCycleTransitionImpl; -
LifeCycleManagerImpl: this class implementsLifeCycleManagerand is a bean which can be instantiated with a collection ofLifeCycleStateand which can be used to run a requested transition; -
LifeCycleChangeSaver: this interface should be implemented in order to save success transition with the following information:- LifeCycle id
- Transition id
- Value object id
- Value object type
- Date of change
- State in (state before transition)
- State out (state after transition)
-
LogLifeCycleChangeSaverImpl: this class is the default used implementation ofLifeCycleChangeSaver(with a slf4j info trace only).
-
-
org.volifecycle.transcocomponents:-
TranscoImpl: this class is an implementation ofTransco(which extendsjava.util.map) and allows us to use a bidirectional hash table.
-
-
org.volifecycle.eventcomponents:-
EventManager: this interface should be implemented in order to save some event (validation failure for example) with the following information:- Actor which is responsible for this event
- Date of event
- Value object (which is affected by the event) id
- Value object (which is affected by the event) type
- Type of event (failure, ...)
- Custom message
-
LogEventManagerImpl: this class is the default used implementation ofEventManager(with a slf4j info trace only); -
DiffDetectorImpl: this is a bean which can be instantiated in order to compare and save all differences between both versions of a value object (and his children) with an implementation ofEventManager.
-

- First case (blue case):
- 1 transition (
LifeCycleTransitionImpl) - 3 simple actions (
? extends LifeCycleSimpleActionImpl): C1, C2, C3 which returns "true" or "false" - only one target state "STATE 1"
- 1 transition (
- Second case (black case):
- 1 transition (
LifeCycleTransitionImpl) with two target states ("STATE 1" and "STATE 2") - 1 composite action (
LifeCycleCompositeActionImpl) with:- the target state "STATE 2"
- 4 simple actions (
? extends LifeCycleSimpleActionImpl): C1, C2, C3, C4
- 1 composite action (
LifeCycleCompositeActionImpl) with:- the target state "STATE 3"
- 3 simple actions (
? extends LifeCycleSimpleActionImpl): C1, C2, C3 (!C4 is implicit)
- 1 transition (
Here is a BPMN case:

Here is a sample of single Spring configuration file to manage all states's transitions for this case:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:context="http://www.springframework.org/schema/context" xmlns:util="http://www.springframework.org/schema/util" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd">
<!-- Transco table which can be used in the adapter -->
<bean id="vo1TranscoStates" class="org.volifecycle.transco.impl.TranscoImpl">
<property name="map">
<map key-type="java.lang.String" value-type="java.lang.String">
<entry key="STATE1" value="{id in database}" />
<entry key="STATE2" value="{id in database}" />
<entry key="STATE3" value="{id in database}" />
</map>
</property>
</bean>
<!-- Event manager and change saver (not mandatory) -->
<bean id="customEvtManager" class="org.yourproject.event.CustomEventManager" />
<bean id="cusomChangeSaver" class="org.yourproject.event.CustomChangeSaver" />
<!-- Adapters declarations -->
<bean id="vo1Adapter" class="org.yourproject.adapter.VO1Adapter" />
<!-- Actions declarations -->
<bean id="actionCheckDateValidated" class="org.yourproject.actions.CheckIsDateValidated">
<property name="id" value="actionCheckDateValidated" />
<property name="description" value="Assert : the object have got a setted validation date" />
</bean>
<bean id="actionCompositeCase1" class="org.volifecycle.lifecycle.impl.LifeCycleCompositeActionImpl">
<property name="id" value="actionCompositeCase1" />
<property name="description" value="Case 1 : date is valid" />
<property name="targetState" value="STATE2" />
<!-- Opérations de vérification -->
<property name="actions">
<list>
<ref bean="actionCheckDateValidated" />
</list>
</property>
</bean>
<bean id="actionCompositeCase2" class="org.volifecycle.lifecycle.impl.LifeCycleCompositeActionImpl">
<property name="id" value="actionCompositeCase2" />
<property name="description" value="Case 2 : date isn't valid" />
<property name="targetState" value="STATE3" />
<!-- Opérations de vérification -->
<property name="actions">
<list>
</list>
</property>
</bean>
<!-- Transitions declarations -->
<bean id="transitionToState2OrState3" class="org.volifecycle.lifecycle.impl.LifeCycleTransitionImpl">
<!-- Type and description -->
<property name="type" value="manual" />
<property name="description" value="Change to STATE2" />
<!-- Target state -->
<property name="targetStates">
<list>
<value>STATE2</value>
<value>STATE3</value>
</list>
</property>
<!-- Actions/checkers -->
<property name="actions">
<list>
<ref bean="actionCompositeCase1" />
<ref bean="actionCompositeCase2" />
</list>
</property>
</bean>
<!-- States declarations -->
<bean id="STATE1" class="org.volifecycle.lifecycle.impl.LifeCycleStateImpl">
<!-- Id and description -->
<property name="id" value="STATE1" />
<property name="description" value="State 1" />
<!-- Transitions by state id -->
<property name="transitionsById">
<map key-type="java.lang.String" value-type="org.volifecycle.lifecycle.impl.LifeCycleTransitionImpl">
<entry key="TR_ST2_OR_ST3" value-ref="transitionToState2OrState3" />
</map>
</property>
</bean>
<bean id="STATE2" class="org.volifecycle.lifecycle.impl.LifeCycleStateImpl">
<!-- Id and description -->
<property name="id" value="STATE2" />
<property name="description" value="State 2" />
<!-- Transitions by state id -->
<property name="transitionsById">
<map key-type="java.lang.String" value-type="org.volifecycle.lifecycle.impl.LifeCycleTransitionImpl">
</map>
</property>
</bean>
<bean id="STATE3" class="org.volifecycle.lifecycle.impl.LifeCycleStateImpl">
<!-- Id and description -->
<property name="id" value="STATE3" />
<property name="description" value="State 3" />
<!-- Transitions by state id -->
<property name="transitionsById">
<map key-type="java.lang.String" value-type="org.volifecycle.lifecycle.impl.LifeCycleTransitionImpl">
</map>
</property>
</bean>
<!-- Lifecycle managers declaration -->
<bean id="vo1LifeCycleManager" class="org.volifecycle.lifecycle.impl.LifeCycleManagerImpl">
<!-- Id and description -->
<property name="id" value="VO1_LIFECYCLE" />
<property name="description" value="VO1 Lifecycle" />
<!-- Lifecycle's state -->
<property name="statesById">
<map key-type="java.lang.String" value-type="org.volifecycle.lifecycle.impl.LifeCycleStateImpl">
<entry key="STATE1" value-ref="STATE1" />
<entry key="STATE2" value-ref="STATE2" />
<entry key="STATE3" value-ref="STATE3" />
</map>
</property>
<property name="adapter" ref="vo1Adapter" />
<property name="evtManager" ref="customEvtManager" />
<property name="saver" ref="cusomChangeSaver" />
</bean>
</beans>Here is a sample of single Spring configuration file to manage diff detector on both versions of a value object:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:context="http://www.springframework.org/schema/context" xmlns:util="http://www.springframework.org/schema/util" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd">
<!-- Event manager and change saver (not mandatory) -->
<bean id="customEvtManager" class="org.yourproject.event.CustomEventManager" />
<!-- listeners -->
<bean id="valueObjectListener" class="org.volifecycle.event.ClassListener">
<property name="className" value="org.yourproject.vo.ValueObject" />
<property name="properties">
<list>
<value>code</value>
<value>label</value>
</list>
</property>
</bean>
<bean id="subValueObjectListener" class="org.volifecycle.event.ClassListener">
<property name="className" value="org.yourproject.vo.SubValueObject" />
<property name="properties">
<list>
<value>something</value>
</list>
</property>
</bean>
<!-- diff detector bean -->
<bean id="voDiffDetector" class="org.volifecycle.event.impl.DiffDetectorImpl">
<property name="evtManager" ref="customEvtManager" />
<property name="classListeners">
<list>
<ref bean="valueObjectListener" />
<ref bean="subValueObjectListener" />
</list>
</property>
</bean>
</beans>This examples are provided for JEE projects using Spring and JPA/Hibernate.
Here is an example of repository with new implementations of saveAndFlush method:
- You could extends this interface with your own repositories and use @Repository annotation;
- This interface is Java 8 compliant with default methods. In lower versions of Java, you can extends SimpleJpaRepository or use Hibernate interceptors instead.
import java.io.Serializable;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
import org.volifecycle.event.DiffDetector;
import org.volifecycle.lifecycle.LifeCycleAdapter;
/**
* Custom repository with diffDetector information saving
*
* @author Idriss Neumann <neumann.idriss@gmail.com>
*
* @param <T> entity type
* @param <I> id type
*/
public interface DiffDetectorRepository<T, I extends Serializable> extends JpaSpecificationExecutor<T>, JpaRepository<T, I> {
/**
* New implementation of saveAndFlush with parent informations
*/
default T saveAndFlush(I id, String parentId, String parentType, T entity, DiffDetector<T, LifeCycleAdapter<T>> detector) {
T previous = (null == id) ? null : (T) findOne(id);
if (null != detector) {
detector.compare(previous, entity, parentId, parentType);
}
return saveAndFlush(entity);
}
/**
* New implementation of saveAndFlush
*/
default T saveAndFlush(I id, T entity, DiffDetector<T, LifeCycleAdapter<T>> detector) {
T previous = (null == id) ? null : (T) findOne(id);
if (null != detector) {
detector.compare(previous, entity);
}
return saveAndFlush(entity);
}
}import org.springframework.beans.factory.annotation.Autowired;
import org.volifecycle.event.EventManager;
import org.volifecycle.event.vo.Event;
import org.volifecycle.utils.BeanMapperFactory;
/**
* Example of implementation of EventManager
*
* @author Idriss Neumann <neumann.idriss@gmail.com>
*
*/
public class CustomEventManager implements EventManager {
@Autowired
private YourRepository repository;
/**
* {@inheritDoc}
*/
@Override
public void logEvent(Event src) {
YourEntity target = BeanMapperFactory.getInstance().map(src, YourEntity.class);
repository.save(target);
}
}