@Override
  public void afterPropertiesSet() {
    try {
      if (this.mappingContext == null) this.mappingContext = new Neo4jMappingContext();
      if (this.graphDatabaseService == null && graphDatabase instanceof DelegatingGraphDatabase) {
        this.graphDatabaseService =
            ((DelegatingGraphDatabase) graphDatabase).getGraphDatabaseService();
      }
      if (this.graphDatabase == null) {
        this.graphDatabase = new DelegatingGraphDatabase(graphDatabaseService);
      }
      if (this.transactionManager == null) {
        this.transactionManager = new JtaTransactionManager(graphDatabase.getTransactionManager());
      }
      if (this.conversionService == null) {
        this.conversionService = new Neo4jConversionServiceFactoryBean().getObject();
      }
      if (nodeEntityInstantiator == null) {
        nodeEntityInstantiator = new NodeEntityInstantiator(entityStateHandler);
      }
      if (relationshipEntityInstantiator == null) {
        relationshipEntityInstantiator = new RelationshipEntityInstantiator(entityStateHandler);
      }
      if (this.typeRepresentationStrategyFactory == null) {
        this.typeRepresentationStrategyFactory =
            new TypeRepresentationStrategyFactory(graphDatabase);
      }
      if (this.nodeTypeRepresentationStrategy == null) {
        this.nodeTypeRepresentationStrategy =
            typeRepresentationStrategyFactory.getNodeTypeRepresentationStrategy();
      }
      if (this.relationshipTypeRepresentationStrategy == null) {
        this.relationshipTypeRepresentationStrategy =
            typeRepresentationStrategyFactory.getRelationshipTypeRepresentationStrategy();
      }
      if (this.nodeEntityStateFactory == null) {
        this.nodeEntityStateFactory =
            new NodeEntityStateFactory(
                mappingContext, new NodeDelegatingFieldAccessorFactory.Factory());
      }
      if (this.relationshipEntityStateFactory == null) {
        this.relationshipEntityStateFactory =
            new RelationshipEntityStateFactory(
                mappingContext, new RelationshipDelegatingFieldAccessorFactory.Factory());
      }
      this.typeRepresentationStrategies =
          new TypeRepresentationStrategies(
              mappingContext,
              nodeTypeRepresentationStrategy,
              relationshipTypeRepresentationStrategy);

      final EntityStateHandler entityStateHandler =
          new EntityStateHandler(mappingContext, graphDatabase);
      EntityTools<Node> nodeEntityTools =
          new EntityTools<Node>(
              nodeTypeRepresentationStrategy,
              nodeEntityStateFactory,
              nodeEntityInstantiator,
              mappingContext);
      EntityTools<Relationship> relationshipEntityTools =
          new EntityTools<Relationship>(
              relationshipTypeRepresentationStrategy,
              relationshipEntityStateFactory,
              relationshipEntityInstantiator,
              mappingContext);
      this.entityPersister =
          new Neo4jEntityPersister(
              conversionService,
              nodeEntityTools,
              relationshipEntityTools,
              mappingContext,
              entityStateHandler);
      this.entityRemover =
          new EntityRemover(
              this.entityStateHandler,
              nodeTypeRepresentationStrategy,
              relationshipTypeRepresentationStrategy,
              graphDatabase);
      if (this.resultConverter == null) {
        this.resultConverter = new EntityResultConverter<Object, Object>(conversionService);
      }
      this.graphDatabase.setResultConverter(resultConverter);
      this.cypherQueryExecutor =
          new CypherQueryExecutor(graphDatabase.queryEngineFor(QueryType.Cypher, resultConverter));
      if (this.indexProvider == null) {
        this.indexProvider = new IndexProviderImpl(this.mappingContext, graphDatabase);
      }
      this.mappingInfrastructure =
          new MappingInfrastructure(
              graphDatabase,
              graphDatabaseService,
              indexProvider,
              resultConverter,
              transactionManager,
              typeRepresentationStrategies,
              entityRemover,
              entityPersister,
              entityStateHandler,
              cypherQueryExecutor,
              mappingContext,
              relationshipTypeRepresentationStrategy,
              nodeTypeRepresentationStrategy,
              validator,
              conversionService);
    } catch (Exception e) {
      throw new RuntimeException("error initializing " + getClass().getName(), e);
    }
  }