Uploaded image for project: 'Ignite'
  1. Ignite
  2. IGNITE-6462

@SpringResource block Service Node bootstrap when the node starts at the first time

    XMLWordPrintableJSON

    Details

    • Type: Bug
    • Status: Open
    • Priority: Major
    • Resolution: Unresolved
    • Affects Version/s: 2.1, 2.2
    • Fix Version/s: None
    • Component/s: managed services, spring
    • Labels:
      None
    • Environment:

      OS: OSX 10.12
      Java: 1.8.0_112-b16
      Kotlin: 1.1.4-3

      Description

      @SpringResource block Service Node bootstrap and service deployment when the node starts at the first time. After killing the service node and restarting, the service is deployed successfully.

      My steps is

      1. Start the data node

      ```
      fun main(args: Array<String>) {
      SpringApplication(DataNodeApplication::class.java).apply {
      addInitializers(
      ApplicationContextInitializer<GenericApplicationContext>

      { DataNodeApplication.beans().initialize(it) }

      )
      }.run(*args)
      }

      @SpringBootConfiguration
      @EnableAutoConfiguration
      class DataNodeApplication {

      companion object {
      fun beans() = beans {
      bean("igniteInstance") {
      // Ignite configuration with all defaults
      // and enabled p2p deployment and enabled events.
      val igniteConfig = IgniteConfiguration().apply {
      isPeerClassLoadingEnabled = true

      /*
      Labeling Data Nodes with special attribute.
      This attribute is checked by common.filters.DataNodeFilters
      which decides where caches have to be deployed.
      */
      userAttributes = mutableMapOf("data.node" to true)

      // Configuring caches that will be deployed on Data Nodes
      setCacheConfiguration(
      // Cache for QuoteRequest
      CacheConfiguration<Int, QuoteRequest>().apply

      { name = "QuoteRequest" /* Enabling a special nodes filter for the cache. The filter will make sure that the cache will be deployed only on Data Nodes, the nodes that have 'data.node' attribute in the local node map. */ nodeFilter = DataNodeFilter() }

      ,
      // Cache for Maintenance records
      CacheConfiguration<Int, Maintenance>().apply {
      name = "maintenance"
      /*
      Enabling a special nodes filter for the cache. The filter
      will make sure that the cache will be deployed only on Data
      Nodes, the nodes that have 'data.node' attribute in the local
      node map.
      */
      nodeFilter = DataNodeFilter()

      // Enabling our sample cache store for the Maintenance cache
      setCacheStoreFactory(FactoryBuilder.factoryOf("common.cachestore.SimpleCacheStore"))

      // Avoid Maintenance objects deserialization on data nodes side
      // when they are passed to SampleCacheStore.
      isStoreKeepBinary = true

      // Enabling the write-through feature for the store.
      isWriteThrough = true

      // Enabling the read-through feature for the store.
      isReadThrough = true

      // Configuring SQL schema.
      queryEntities = listOf(
      QueryEntity().apply

      { // Setting indexed type's key class keyType = "java.lang.Integer" // Setting indexed type's value class valueType = "entity.Maintenance" // Defining fields that will be either indexed or queryable. // Indexed fields are added to 'indexes' list below. fields = linkedMapOf("vehicleId" to "java.lang.Integer") // Defining indexed fields. // Single field (aka. column) index indexes = listOf(QueryIndex("vehicleId")) }

      )
      }
      )

      discoverySpi = discoverySpi()
      }

      IgniteSpringBean().apply

      { configuration = igniteConfig }
      }
      }
      }
      }
      ```

      2. Start the service node

      ```
      fun main(args: Array<String>) {
      SpringApplication(RequestForQuoteServiceNode::class.java).apply {
      addInitializers(
      ApplicationContextInitializer<GenericApplicationContext> { RequestForQuoteServiceNode.beans().initialize(it) }
      )
      }.run(*args)
      }

      @SpringBootConfiguration
      @EnableAutoConfiguration
      @EnableIgniteRepositories("repository")
      class RequestForQuoteServiceNode {

      companion object {
      fun beans() = beans {
      bean("igniteInstance") {
      // Ignite configuration with all defaults
      // and enabled p2p deployment and enabled events.
      val igniteConfig = IgniteConfiguration().apply {
      isPeerClassLoadingEnabled = true

      /*
      Labeling QuoteRequest Service nodes with special attribute.
      This attribute is checked by common.filters.VehicleServiceFilter.
      Due to the filter, the RequestForQuoteService might be deployed only on
      the nodes with this special attribute set.
      */
      userAttributes = mutableMapOf("vehicle.service.node" to true)

      setServiceConfiguration(
      // Setting up RequestForQuoteService.
      // The service will be deployed automatically
      // according to the configuration below.
      ServiceConfiguration().apply { name = "RequestForQuoteService" // Don't initialize service's properties here. Ignite's deployment // will discard them. service = RequestForQuoteServiceImpl() // Only one instance of the service will be deployed cluster wide totalCount = 1 // Only one instance of the service can be deployed on a single node. maxPerNodeCount = 1 /* Enabling a special nodes filter for this service. The filter will make sure that the service will be deployed only on the nodes that have 'quoteRequest.service.node' attribute in the local node map. */ nodeFilter = VehicleServiceFilter() }
      )

      discoverySpi = discoverySpi()
      }

      IgniteSpringBean().apply { configuration = igniteConfig }

      }
      }
      }

      }
      ```
      class RequestForQuoteServiceImpl : RequestForQuoteService {

      @Transient @SpringResource(resourceClass = QuoteRequestRepository::class)
      lateinit var quoteRequestRepository: QuoteRequestRepository

      @IgniteInstanceResource
      lateinit var ignite: Ignite

      /** Reference to the cache. */
      lateinit private var quoteRequestCache: IgniteCache<Int, QuoteRequest>

      /**

      {@inheritDoc} */
      override fun init(ctx: ServiceContext) { println("Initializing RequestForQuote Service on node:" + ignite.cluster().localNode()) /** * It's assumed that the cache has already been deployed. To do that, make sure to start Data Nodes with * a respective cache configuration. */ quoteRequestCache = ignite.cache("QuoteRequest") }

      /** {@inheritDoc}

      */
      override fun execute(ctx: ServiceContext)

      { println("Executing QuoteRequest Service on node:" + ignite.cluster().localNode()) // Some custom logic. }

      /**

      {@inheritDoc} */
      override fun cancel(ctx: ServiceContext) { println("Stopping QuoteRequest Service on node:" + ignite.cluster().localNode()) // Some custom logic. }

      /** {@inheritDoc}

      */
      override fun addQuoteRequest(quoteRequestId: Int, quoteRequest: QuoteRequest)

      { // quoteRequestCache.put(quoteRequestId, quoteRequest) println("incoming Quote Request: id = $quoteRequestId, $quoteRequest") quoteRequestRepository.save(quoteRequestId, quoteRequest) }

      /**

      {@inheritDoc} */
      override fun getQuoteRequest(quoteRequestId: Int): QuoteRequest { return quoteRequestCache.get(quoteRequestId) }

      /** {@inheritDoc}

      */
      override fun removeQuoteRequest(quoteRequestId: Int)

      { quoteRequestCache.remove(quoteRequestId) }

      }
      ```

      ```
      interface RequestForQuoteService : Service {

      /**

      • Calls the service to add a new quoteRequest.
        *
      • @param quoteRequestId QuoteRequest unique ID.
      • @param quoteRequest QuoteRequest instance to add.
        */
        fun addQuoteRequest(quoteRequestId: Int, quoteRequest: QuoteRequest)

      /**

      • Calls the service to get details for a specific QuoteRequest.
        *
      • @param quoteRequestId QuoteRequest unique ID.
        */
        fun getQuoteRequest(quoteRequestId: Int): QuoteRequest

      /**

      • Calls the service to remove a specific vehicle.
        *
      • @param quoteRequestId QuoteRequest unique ID.
        */
        fun removeQuoteRequest(quoteRequestId: Int)
        }
        ```

      ```
      public class VehicleServiceFilter implements IgnitePredicate<ClusterNode> {
      /**

      • Checks if {@code node}

        needs to be considered as a QuoteRequest Service Node.
        *

      • @param node Cluster node instance.
        *
      • @return {@code true}

        if the node has to be considered as QuoteRequest Service Node,

        {@code false}

        otherwise.
        */
        public boolean apply(ClusterNode node)

        { Boolean dataNode = node.attribute("vehicle.service.node"); return dataNode != null && dataNode; }

        }
        ```

      ```
      @RepositoryConfig(cacheName = "QuoteRequest")
      interface QuoteRequestRepository : IgniteRepository<QuoteRequest, Int>
      ```

        Attachments

          Activity

            People

            • Assignee:
              Unassigned
              Reporter:
              redtankd redtank
            • Votes:
              0 Vote for this issue
              Watchers:
              1 Start watching this issue

              Dates

              • Created:
                Updated: