You are viewing a plain text version of this content. The canonical link for it is here.
Posted to issues@ignite.apache.org by "redtank (JIRA)" <ji...@apache.org> on 2017/09/21 02:41:00 UTC

[jira] [Created] (IGNITE-6462) @SpringResource block Service Node bootstrap when the node starts at the first time

redtank created IGNITE-6462:
-------------------------------

             Summary: @SpringResource block Service Node bootstrap when the node starts at the first time
                 Key: IGNITE-6462
                 URL: https://issues.apache.org/jira/browse/IGNITE-6462
             Project: Ignite
          Issue Type: Bug
          Components: managed services, spring
    Affects Versions: 2.1, 2.2
         Environment: OS: OSX 10.12
Java: 1.8.0_112-b16
Kotlin: 1.1.4-3
            Reporter: redtank


@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>
```



--
This message was sent by Atlassian JIRA
(v6.4.14#64029)