Skip to content

Getting started

Idriss Neumann edited this page Jun 3, 2015 · 91 revisions

Table of content

Installation with maven

Maven repository

<repository>
    <id>vo-lifecycle-mvn-repo</id>
    <url>https://raw.github.com/idrissneumann/vo-lifecycle/mvn-repo/</url>
    <snapshots>
        <enabled>true</enabled>
        <updatePolicy>always</updatePolicy>
    </snapshots>
</repository>

Maven dependency

<dependency>
    <groupId>vo-lifecycle</groupId>
    <artifactId>vo-lifecycle-core</artifactId>
    <version>${vo-lifecycle.version}</version>
</dependency>

How to use

Main components

  • org.volifecycle.lifecycle components:
    • LifeCycleCheckerImpl (1.0.0): this class is an abstract class which can be extended in order to write a validation state change condition;
    • LifeCycleTransitionImpl (1.0.0): this class is a bean which represents a transition (change of one state to another) with a target state and a collection of LifeCycleCheckerImpl;
    • LifeCycleStateImpl (1.0.0): this class is a bean which represents a value object state and which can be instantiated with a collection of LifeCycleTransitionImpl;
    • LifeCycleManagerImpl (1.0.0): this class is a bean which can be instantiated with a collection of LifeCycleStateImpl and which can be used to run a requested transition;
    • LifeCycleChangeSaver (1.0.0): 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)
    • Log4jLifeCycleChangeSaverImpl (1.0.0): this class is the default used implementation of LifeCycleChangeSaver (with a log4j debug trace only).
  • org.volifecycle.transco components:
    • TranscoImpl (1.0.0): this class is an implementation of java.util.map which allow us to use a two-way hash table.
  • org.volifecycle.event components:
    • EventManager (1.0.0): 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
    • Log4jEventManagerImpl (1.0.0): this class is the default used implementation of EventManager (with a log4j debug trace only);
    • DiffDetectorImpl (1.1.1) : 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 of EventManager.

Spring integration sample

Managing states's transitions for a value object

Here is a sample of single Spring configuration file to manage all states's transitions for a single type of value object (available on 1.0.0 version):

<?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}" />
            </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" />

    <!-- Checkers declarations -->
    <bean id="checkerDateValidated" class="org.yourproject.checkers.IsDateValidated">
        <property name="id" value="IS_ACCEPTED" />
        <property name="description" value="Assert : the object have got a setted validation date" />
    </bean>

    <!-- Transitions declarations -->
    <bean id="transitionToState2" 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="target" value="STATE2" />

        <!-- Checkers -->
        <property name="checkers">
            <list>
                <ref bean="checkerDateValidated" />
            </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="STATE2" value-ref="transitionToState2" />
            </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" />
            </map>
        </property>

        <property name="adapter" ref="vo1Adapter" />
        <property name="evtManager" ref="customEvtManager" />
        <property name="saver" ref="cusomChangeSaver" />
     </bean>
</beans>

Managing diff detector on both versions of a value object

Here is a sample of single Spring configuration file to manage diff detector on both versions of a value object (available on 1.1.1-SNAPSHOT version):

<?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>

Code examples

This examples are provided for JEE projects using Spring and JPA/Hibernate.

Diff dectector implementation with JPA repository

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);
    }
}

Implementation of EventManager with JPA/Repository and Dozer

import org.dozer.DozerBeanMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.volifecycle.event.EventManager;
import org.volifecycle.event.vo.Event;

/**
 * Example of implementation of EventManager
 * 
 * @author Idriss Neumann <neumann.idriss@gmail.com>
 *
 */
public class CustomEventManager implements EventManager {
    @Autowired
    private YourRepository repository;
	
	@Autowired
    private DozerBeanMapper dozerBeanMapper;

    /**
     * {@inheritDoc}
     */
    @Override
    public void logEvent(Event src) {
        YourEntity target = dozerBeanMapper.map(src, YourEntity.class);
        repository.save(target);
    }
}

Clone this wiki locally