You are viewing a plain text version of this content. The canonical link for it is here.
Posted to user@ignite.apache.org by Pim D <pi...@ns.nl> on 2018/01/30 18:26:18 UTC

Serialization problem when combining Spring boot (hateoas) with Ignite

Hi,

I'm encountering an issue when I start an ignite client inside a spring boot
app (with hate-aos).
It seems as if there are classloader or marshalling conflicts between both
frameworks.
Can anyone confirm (or even better: a clue on how to solve this?):




--
Sent from: http://apache-ignite-users.70518.x6.nabble.com/

Re: Serialization problem when combining Spring boot (hateoas) with Ignite

Posted by Pim D <pi...@ns.nl>.
Hi Amir,


Regarding your questions:
1) Clients are not able to communicatie with the nodes in the grid, none of
the ignite messages can be deserialized by the client.
2) The project is to big to share for reproduction, but I try to provide the
relevant parts.
Server(s):

    @Bean
    @Scope(BeanDefinition.SCOPE_SINGLETON)
    @DependsOn(value = "playerScoreDS")
    public Ignite getIgnite() throws IgniteCheckedException {
        Map<String,Object> attr = new HashMap<>();
        attr.put(ClusterUtils.GROEP,groepen);
        FlipperkastClusterConfiguratie conf = new
FlipperkastClusterConfiguratie();
        conf.setUserAttributes(attr);
        conf.setAddresses(servers);
        conf.setLifecycleBeans(
                new NodeCacheEventListener()
                ,new PlungerActivator()
                ,new GootActivator()
                ,new WaxPhantomActivator()
                ,new PescadoDiabolicoActivator()
                ,new BackboxActivator()
                ,new BackboxAccessActivator()
        );
        return IgniteSpring.start(conf,context);
    }

Client:

    @Bean
    public IgniteConfiguration getIgniteConfiguratie() {
        FlipperkastClusterConfiguratie conf = new
FlipperkastClusterConfiguratie(); // (has peerClassloading disabled and the
log4j2 logger and Ignite Home set to the folder where the application is
started)
        conf.setIgniteInstanceName(naam);
        conf.setClientMode(true);
        Map<String,List&lt;String>> attr = new HashMap<>();
        attr.put(ClusterUtils.GROEP,groepen);
        conf.setUserAttributes(attr);
        conf.setAddresses(servers);
        return conf;
    }
    
    @Bean
    public Ignite getIgnite() throws IgniteCheckedException {
        if (client == null) {
            synchronized (this) {
                if (client == null) {
                    FlipperkastClusterConfiguratie conf = new
FlipperkastClusterConfiguratie();
                    conf.setIgniteInstanceName(naam);
                    conf.setClientMode(true);
                    Map<String, List&lt;String>> attr = new HashMap<>();
                    attr.put(ClusterUtils.GROEP, groepen);
                    conf.setUserAttributes(attr);
                    conf.setAddresses(servers);
                    client = IgniteSpring.start(conf, context);
                }
            }
        }
        return client;
    }

3) The project is to big to share for reproduction.
It requires various frameworks.





--
Sent from: http://apache-ignite-users.70518.x6.nabble.com/

Re: Serialization problem when combining Spring boot (hateoas) with Ignite

Posted by Amir Akhmedov <am...@gmail.com>.
Hi Pim,

Can you please provide more details on your issue?
1. What is the issue and what is the expected behavior?
2. Server and client configurations
3. It would be nice to have a small reproducer for better understanding.

Thanks,
Amir

On Tue, Jan 30, 2018 at 2:19 PM, Pim D <pi...@ns.nl> wrote:

> Update:
> Not quite sure if this is the problem but the issue is with client nodes.
> I have peer class loading disabled and the client is also logging unknown
> classes of Ignite lifecyclebeans which are present on server nodes (but
> definitely NOT on client nodes).
>
> This behaviour seems really awkward to me.
>
>
>
>
>
> --
> Sent from: http://apache-ignite-users.70518.x6.nabble.com/
>

Re: Serialization problem when combining Spring boot (hateoas) with Ignite

Posted by Pim D <pi...@ns.nl>.
Update:
Not quite sure if this is the problem but the issue is with client nodes.
I have peer class loading disabled and the client is also logging unknown
classes of Ignite lifecyclebeans which are present on server nodes (but
definitely NOT on client nodes).

This behaviour seems really awkward to me.





--
Sent from: http://apache-ignite-users.70518.x6.nabble.com/

Re: Serialization problem when combining Spring boot (hateoas) with Ignite

Posted by Pim D <pi...@ns.nl>.
Logging of the client (which should not create the cache, yet somehow it gets
instructed to create the cache on the client node)

2018-01-31T11:15:58.424 INFO  [BackboxPlayerScoreController] - Createdsabled
(to enable configure any GridCheckpointSpi implementation)
2018-01-31T11:15:58.900 WARN  [BinaryContext] - Class
"com.fasterxml.jackson.core.io.SerializedString" cannot be serialized using
BinaryMarshaller because it either implements Externalizable interface or
have writeObject/readObject methods. OptimizedMarshaller will be used
instead and class instances will be deserialized on the server. Please
ensure that all nodes have this class in classpath. To enable binary
serialization either implement Binarylizable interface or set explicit
serializer using BinaryTypeConfiguration.setSerializer() method.
2018-01-31T11:15:58.928 WARN  [BinaryContext] - Class
"com.fasterxml.jackson.databind.util.LRUMap" cannot be serialized using
BinaryMarshaller because it either implements Externalizable interface or
have writeObject/readObject methods. OptimizedMarshaller will be used
instead and class instances will be deserialized on the server. Please
ensure that all nodes have this class in classpath. To enable binary
serialization either implement Binarylizable interface or set explicit
serializer using BinaryTypeConfiguration.setSerializer() method.
2018-01-31T11:15:59.380 INFO  [HighScoreDispatcher] - Geabonneerd op high
score updates
2018-01-31T11:15:59.513 INFO  [MessageDispatcher] - Geabonneerd op message
updates
2018-01-31T11:15:59.532 ERROR [GridCachePartitionExchangeManager] - Failed
to process custom exchange task: ClientCacheChangeDummyDiscoveryMessage
[reqId=98b5ab8a-0822-4617-a477-c710f962df9f, cachesToClose=null,
startCaches=[PlayerScores]]
org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean
named 'playerScoreDS' available
        at
org.springframework.beans.factory.support.DefaultListableBeanFactory.getBeanDefinition(DefaultListableBeanFactory.java:687)
~[spring-beans-4.3.13.RELEASE.jar:4.3.13.RELEASE]
        at
org.springframework.beans.factory.support.AbstractBeanFactory.getMergedLocalBeanDefinition(AbstractBeanFactory.java:1207)
~[spring-beans-4.3.13.RELEASE.jar:4.3.13.RELEASE]
        at
org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:284)
~[spring-beans-4.3.13.RELEASE.jar:4.3.13.RELEASE]
        at
org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197)
~[spring-beans-4.3.13.RELEASE.jar:4.3.13.RELEASE]
        at
org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1080)
~[spring-context-4.3.13.RELEASE.jar:4.3.13.RELEASE]
        at
org.apache.ignite.internal.processors.resource.GridResourceSpringBeanInjector.getBeanByResourceAnnotation(GridResourceSpringBeanInjector.java:120)
~[ignite-spring-2.3.0.jar:2.3.0]
        at
org.apache.ignite.internal.processors.resource.GridResourceSpringBeanInjector.inject(GridResourceSpringBeanInjector.java:64)
~[ignite-spring-2.3.0.jar:2.3.0]
        at
org.apache.ignite.internal.processors.resource.GridResourceIoc$ClassDescriptor.injectInternal(GridResourceIoc.java:440)
~[ignite-core-2.3.0.jar:2.3.0]
        at
org.apache.ignite.internal.processors.resource.GridResourceIoc$ClassDescriptor.inject(GridResourceIoc.java:470)
~[ignite-core-2.3.0.jar:2.3.0]
        at
org.apache.ignite.internal.processors.resource.GridResourceProcessor.inject(GridResourceProcessor.java:278)
~[ignite-core-2.3.0.jar:2.3.0]
        at
org.apache.ignite.internal.processors.resource.GridResourceProcessor.inject(GridResourceProcessor.java:248)
~[ignite-core-2.3.0.jar:2.3.0]
        at
org.apache.ignite.internal.processors.resource.GridResourceProcessor.injectGeneric(GridResourceProcessor.java:229)
~[ignite-core-2.3.0.jar:2.3.0]
        at
org.apache.ignite.internal.processors.cache.GridCacheProcessor.prepare(GridCacheProcessor.java:537)
~[ignite-core-2.3.0.jar:2.3.0]
        at
org.apache.ignite.internal.processors.cache.GridCacheProcessor.prepare(GridCacheProcessor.java:526)
~[ignite-core-2.3.0.jar:2.3.0]
        at
org.apache.ignite.internal.processors.cache.GridCacheProcessor.createCache(GridCacheProcessor.java:1342)
~[ignite-core-2.3.0.jar:2.3.0]
        at
org.apache.ignite.internal.processors.cache.GridCacheProcessor.prepareCacheStart(GridCacheProcessor.java:1799)
~[ignite-core-2.3.0.jar:2.3.0]
        at
org.apache.ignite.internal.processors.cache.CacheAffinitySharedManager.processClientCacheStartRequests(CacheAffinitySharedManager.java:428)
~[ignite-core-2.3.0.jar:2.3.0]
        at
org.apache.ignite.internal.processors.cache.CacheAffinitySharedManager.processClientCachesChanges(CacheAffinitySharedManager.java:611)
~[ignite-core-2.3.0.jar:2.3.0]
        at
org.apache.ignite.internal.processors.cache.GridCacheProcessor.processCustomExchangeTask(GridCacheProcessor.java:338)
~[ignite-core-2.3.0.jar:2.3.0]
        at
org.apache.ignite.internal.processors.cache.GridCachePartitionExchangeManager$ExchangeWorker.processCustomTask(GridCachePartitionExchangeManager.java:2142)
[ignite-core-2.3.0.jar:2.3.0]
        at
org.apache.ignite.internal.processors.cache.GridCachePartitionExchangeManager$ExchangeWorker.body(GridCachePartitionExchangeManager.java:2231)
[ignite-core-2.3.0.jar:2.3.0]
        at
org.apache.ignite.internal.util.worker.GridWorker.run(GridWorker.java:110)
[ignite-core-2.3.0.jar:2.3.0]
        at java.lang.Thread.run(Thread.java:745) [?:1.8.0_112]




--
Sent from: http://apache-ignite-users.70518.x6.nabble.com/

Re: Serialization problem when combining Spring boot (hateoas) with Ignite

Posted by Andrey Mashenkov <an...@gmail.com>.
Pim,

CacheStore instance is required on all nodes if it is configured for
Transactional cache.
as node that initiate transaction is responsible to update store.

Seems, it is design lack that CacheStore is required on all nodes when it
is configured for Atomic cache.
Ignite allow to set CacheStoreFactory in configuration. So, CacheStore
instance itself never transfered among nodes.


I've just think there is dirty hack that may be workable, but note it is
error prone way:
implement CacheStoreFactory that will create DummyStore instance (where all
method throws UnsupportedOperationException) on client nodes if there is no
store class is available.
CacheStoreFactory supports ignite instance injection via
@IgniteInstanceResource annotation.



On Wed, Jan 31, 2018 at 5:45 PM, Pim D <pi...@ns.nl> wrote:

> Hi Andrew,
>
> Indeed, I've changed the lambda / anonymous class with field to become an
> actual class.
> This fixed one of the problems.
> The other problem is more of a design issue: CacheStoreAdapters are part of
> the CacheConfiguration that is being exchanged between nodes. This
> basically
> requires nodes to have this CacheStoraAdapter on it's classpath, even
> though
> the nodes don't use them. :(
>
>
>
> --
> Sent from: http://apache-ignite-users.70518.x6.nabble.com/
>



-- 
Best regards,
Andrey V. Mashenkov

Re: Serialization problem when combining Spring boot (hateoas) with Ignite

Posted by Вячеслав Коптилин <sl...@gmail.com>.
Hi Pim,

This is a known issue that is not resolved yet
https://issues.apache.org/jira/browse/IGNITE-1903

Thanks!

2018-01-31 17:45 GMT+03:00 Pim D <pi...@ns.nl>:

> Hi Andrew,
>
> Indeed, I've changed the lambda / anonymous class with field to become an
> actual class.
> This fixed one of the problems.
> The other problem is more of a design issue: CacheStoreAdapters are part of
> the CacheConfiguration that is being exchanged between nodes. This
> basically
> requires nodes to have this CacheStoraAdapter on it's classpath, even
> though
> the nodes don't use them. :(
>
>
>
> --
> Sent from: http://apache-ignite-users.70518.x6.nabble.com/
>

Re: Serialization problem when combining Spring boot (hateoas) with Ignite

Posted by Pim D <pi...@ns.nl>.
Hi Andrew,

Indeed, I've changed the lambda / anonymous class with field to become an
actual class.
This fixed one of the problems.
The other problem is more of a design issue: CacheStoreAdapters are part of
the CacheConfiguration that is being exchanged between nodes. This basically
requires nodes to have this CacheStoraAdapter on it's classpath, even though
the nodes don't use them. :(



--
Sent from: http://apache-ignite-users.70518.x6.nabble.com/

Re: Serialization problem when combining Spring boot (hateoas) with Ignite

Posted by Andrey Mashenkov <an...@gmail.com>.
Hi Pim,

It is possible anonymous class can't be serialized due to some reason:
nl.donna.workshop.ignite.flipperkast.api.cluster.FlipperkastCluster$2

Oracle JVM docs recommend to avoid anonymous classes and lambdas
serialization.
We also recommend to avoid inner (non-static) classes as well as they can
have implicit references to their parents.

[1]
https://docs.oracle.com/javase/tutorial/java/javaOO/lambdaexpressions.html#serialization

On Wed, Jan 31, 2018 at 4:54 PM, Pim D <pi...@ns.nl> wrote:

> UPDATE:
>
> I've created an implementation for the IgnitePredicate<ClusterNode> which
> is
> available on both sides (client/server node).
> This solved the serialization issue with the CacheConfiguration.
>
> Next problem:
> The cache store adapter backing one of the caches, is not known by the
> client (and I don't want this dependency in the client either).
> The design of Ignite regarding this part bothers me.
> I guess to only solution left is to let an IgniteService do the continuous
> queries and stream the events using React... :(
>
>
>
>
> --
> Sent from: http://apache-ignite-users.70518.x6.nabble.com/
>



-- 
Best regards,
Andrey V. Mashenkov

Re: Serialization problem when combining Spring boot (hateoas) with Ignite

Posted by Pim D <pi...@ns.nl>.
UPDATE:

I've created an implementation for the IgnitePredicate<ClusterNode> which is
available on both sides (client/server node).
This solved the serialization issue with the CacheConfiguration.

Next problem:
The cache store adapter backing one of the caches, is not known by the
client (and I don't want this dependency in the client either).
The design of Ignite regarding this part bothers me.
I guess to only solution left is to let an IgniteService do the continuous
queries and stream the events using React... :(




--
Sent from: http://apache-ignite-users.70518.x6.nabble.com/

Re: Serialization problem when combining Spring boot (hateoas) with Ignite

Posted by Pim D <pi...@ns.nl>.
P.s. the stacktrace when using a static method as proposed by Val:
Classes:

public class WaxPhantomDataActivator implements LifecycleBean {
    @IgniteInstanceResource
    private Ignite grid;
    private IgnitePredicate<ClusterNode> filter =
FlipperkastCluster.spookhuis().data().nodeFilter();
    @Override
    public void onLifecycleEvent(LifecycleEventType event) throws
IgniteException {
        if (event == LifecycleEventType.AFTER_NODE_START) {
            if (filter.apply(grid.cluster().localNode())) {
                grid.getOrCreateCache(new
WaxPhantomCacheConfiguratie<>(filter));
            }
        }
    }
}

public class WaxPhantomCacheConfiguratie extends
FlipperkastCacheConfiguratie {

    public static final String NAAM = "WaxPhantom";

    public WaxPhantomCacheConfiguratie() {
        this(null);
    }

    public WaxPhantomCacheConfiguratie(IgnitePredicate<ClusterNode> filter)
{
        super(filter);
        setName(NAAM);
    }
}

Stacktrace:

Caused by: org.apache.ignite.IgniteCheckedException: Failed to serialize
object: CacheConfiguration [name=WaxPhantom, grpName=null, memPlcName=null,
storeConcurrentLoadAllThreshold=5, rebalancePoolSize=2,
rebalanceTimeout=10000, evictPlc=null, onheapCache=true, evictFilter=null,
eagerTtl=true, dfltLockTimeout=0, nearCfg=null, writeSync=PRIMARY_SYNC,
storeFactory=null, storeKeepBinary=false, loadPrevVal=false, aff=null,
cacheMode=PARTITIONED, atomicityMode=ATOMIC, backups=0, invalidate=false,
tmLookupClsName=null, rebalanceMode=ASYNC, rebalanceOrder=0,
rebalanceBatchSize=524288, rebalanceBatchesPrefetchCnt=2,
maxConcurrentAsyncOps=500, sqlIdxMaxInlineSize=-1, writeBehindEnabled=false,
writeBehindFlushSize=10240, writeBehindFlushFreq=5000,
writeBehindFlushThreadCnt=1, writeBehindBatchSize=512,
writeBehindCoalescing=true, maxQryIterCnt=1024, affMapper=null,
rebalanceDelay=0, rebalanceThrottle=0, interceptor=null,
longQryWarnTimeout=3000, qryDetailMetricsSz=0, readFromBackup=true,
nodeFilter=nl.donna.workshop.ignite.flipperkast.api.cluster.FlipperkastCluster$2@17f6ab76,
sqlSchema=null, sqlEscapeAll=false, cpOnRead=true, topValidator=null,
partLossPlc=IGNORE, qryParallelism=1]




--
Sent from: http://apache-ignite-users.70518.x6.nabble.com/

Re: Serialization problem when combining Spring boot (hateoas) with Ignite

Posted by Pim D <pi...@ns.nl>.
UPDATE:

Wiring the application context instead of the bean helped solve the problem
in exchanging the cahce configuration (and it's cachestoreadapter).

Now I'm only stuck on this when I exclude the jars which the client should
not have knowledge of: 
Caused by: java.lang.ClassCastException: cannot assign instance of
java.lang.invoke.SerializedLambda to field
org.apache.ignite.configuration.CacheConfiguration.nodeFilter of type
org.apache.ignite.lang.IgnitePredicate in instance of
org.apache.ignite.configuration.CacheConfiguration

At first I used this property to set the node filter which resulted in an
unsuccesfull serialization attempt by Ignite on the static method :
private IgnitePredicate<ClusterNode> filter =
FlipperkastCluster.backbox().data().nodeFilter();

Thus I changed this to:
    private IgnitePredicate<ClusterNode> filter = ClusterNode ->
FlipperkastCluster.backbox().data().nodeFilter().apply(ClusterNode);
And now the client receives an SerializedLambda which can not be resolved.

So how should I do this....



--
Sent from: http://apache-ignite-users.70518.x6.nabble.com/

Re: Serialization problem when combining Spring boot (hateoas) with Ignite

Posted by Pim D <pi...@ns.nl>.
UPDATE:

I guess my issue is related to
http://apache-ignite-users.70518.x6.nabble.com/Client-requires-DataSource-bean-configuration-copy-td15491.html

My caches are ATOMIC and because I want to externalize my datasource
configuration (by making it a Spring bean), I have issues now.

So how can I avoid the client from getting confronted with this cache
configuration?
Should I move my continuous queries to a service in a node and let that
service provide a flux (Reactive)?
Should I wire the spring context instead of the bean and look it up when
needed (client should not need it)?



--
Sent from: http://apache-ignite-users.70518.x6.nabble.com/

Re: Serialization problem when combining Spring boot (hateoas) with Ignite

Posted by Pim D <pi...@ns.nl>.
UPDATE:
I've put all my classes on the classpath of the client.
Now I get a different issue.
One of the caches in the grid has a CacheStoreAdapter which requires a
SpringResource which is not available on the client.
The client does not create this cache (lookup by name), the server data
nodes do this.
Bit puzzled why the client is confronted with the cache configuration.



--
Sent from: http://apache-ignite-users.70518.x6.nabble.com/

Re: Serialization problem when combining Spring boot (hateoas) with Ignite

Posted by Pim D <pi...@ns.nl>.
Hi Val,

This nodeFilter is in fact created from a static utility class.
However I had to provide the lambda
(IgnitePredicate<ClusterNode>&Serializable) because Ignite could not
serialiize the static method.

What I find strange is that the cache configurations in the grid are
communicated to a client node.
And if this is normal, how can it be that the ignite classes
(IgnitePredicate<ClusterNode> which extends Serializable) can not be
serialized?



--
Sent from: http://apache-ignite-users.70518.x6.nabble.com/

Re: Serialization problem when combining Spring boot (hateoas) with Ignite

Posted by vkulichenko <va...@gmail.com>.
Looks like you have a node filter in cache configuration and using lambda to
provide it. I would recommend to create a static class instead, deploy it on
all nodes in topology (both clients and servers) and then restart. Most
likely the issue will go away.

-Val



--
Sent from: http://apache-ignite-users.70518.x6.nabble.com/